~const trait or projection bounds do not imply non-const bounds
This commit is contained in:
parent
0ee9cfd54d
commit
e44b11f695
@ -45,24 +45,6 @@ pub fn push_trait_bound(
|
|||||||
polarity: ty::ImplPolarity,
|
polarity: ty::ImplPolarity,
|
||||||
) {
|
) {
|
||||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
||||||
|
|
||||||
// push a non-const (`host = true`) version of the bound if it is `~const`.
|
|
||||||
if tcx.features().effects
|
|
||||||
&& let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index
|
|
||||||
&& trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_
|
|
||||||
{
|
|
||||||
let generics = tcx.generics_of(trait_ref.def_id());
|
|
||||||
let Some(host_index) = generics.host_effect_index else { return };
|
|
||||||
let trait_ref = trait_ref.map_bound(|mut trait_ref| {
|
|
||||||
trait_ref.args =
|
|
||||||
tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| {
|
|
||||||
if host_index == n { tcx.consts.true_.into() } else { arg }
|
|
||||||
}));
|
|
||||||
trait_ref
|
|
||||||
});
|
|
||||||
|
|
||||||
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_trait_bound_inner(
|
fn push_trait_bound_inner(
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
|
use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{sym, Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
||||||
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
|
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
|
||||||
@ -38,38 +38,12 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
|
|||||||
// an obligation and instead be skipped. Otherwise we'd use
|
// an obligation and instead be skipped. Otherwise we'd use
|
||||||
// `tcx.def_span(def_id);`
|
// `tcx.def_span(def_id);`
|
||||||
let span = rustc_span::DUMMY_SP;
|
let span = rustc_span::DUMMY_SP;
|
||||||
let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) {
|
|
||||||
// when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound,
|
result.predicates =
|
||||||
// because only implementing `Self: Trait<.., false>` is currently not possible.
|
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
|
||||||
Some((
|
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
|
||||||
ty::TraitRef::new(
|
|
||||||
tcx,
|
|
||||||
def_id,
|
|
||||||
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
|
|
||||||
if param.is_host_effect() {
|
|
||||||
tcx.consts.true_.into()
|
|
||||||
} else {
|
|
||||||
tcx.mk_param_from_def(param)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.to_predicate(tcx),
|
|
||||||
span,
|
span,
|
||||||
))
|
))));
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
result.predicates = tcx.arena.alloc_from_iter(
|
|
||||||
result
|
|
||||||
.predicates
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.chain(std::iter::once((
|
|
||||||
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
|
|
||||||
span,
|
|
||||||
)))
|
|
||||||
.chain(non_const_bound),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
|
debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
|
||||||
result
|
result
|
||||||
|
@ -9,7 +9,7 @@ fn foo() {}
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fn foo<T: ~const Foo>() {
|
const fn foo<T: ~const Foo>() {
|
||||||
<T as Foo>::Assoc::foo();
|
<T as /* FIXME: ~const */ Foo>::Assoc::foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -6,15 +6,17 @@ LL | type Assoc: ~const Foo;
|
|||||||
|
|
|
|
||||||
= note: this item cannot have `~const` trait bounds
|
= note: this item cannot have `~const` trait bounds
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0277]: the trait bound `T: Foo` is not satisfied
|
||||||
--> $DIR/assoc-type-const-bound-usage.rs:12:5
|
--> $DIR/assoc-type-const-bound-usage.rs:12:6
|
||||||
|
|
|
|
||||||
LL | <T as Foo>::Assoc::foo();
|
LL | <T as /* FIXME: ~const */ Foo>::Assoc::foo();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true`
|
| ^ the trait `Foo` is not implemented for `T`
|
||||||
|
|
|
|
||||||
= note: expected constant `host`
|
help: consider further restricting this bound
|
||||||
found constant `true`
|
|
|
||||||
|
LL | const fn foo<T: ~const Foo + Foo>() {
|
||||||
|
| +++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![allow(internal_features)]
|
||||||
|
#![no_std]
|
||||||
|
#![no_core]
|
||||||
|
#![feature(
|
||||||
|
auto_traits,
|
||||||
|
const_trait_impl,
|
||||||
|
effects,
|
||||||
|
lang_items,
|
||||||
|
no_core,
|
||||||
|
staged_api,
|
||||||
|
unboxed_closures
|
||||||
|
)]
|
||||||
|
#![stable(feature = "minicore", since = "1.0.0")]
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
fn is_const_fn<F>(_: F)
|
||||||
|
where
|
||||||
|
F: const FnOnce<()>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn foo() {}
|
||||||
|
|
||||||
|
is_const_fn(foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ---------------------------------------------------------------------- ///
|
||||||
|
/// Const fn trait definitions
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
#[lang = "fn"]
|
||||||
|
#[rustc_paren_sugar]
|
||||||
|
trait Fn<Args: Tuple>: ~const FnMut<Args> {
|
||||||
|
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
#[lang = "fn_mut"]
|
||||||
|
#[rustc_paren_sugar]
|
||||||
|
trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
|
||||||
|
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
#[lang = "fn_once"]
|
||||||
|
#[rustc_paren_sugar]
|
||||||
|
trait FnOnce<Args: Tuple> {
|
||||||
|
#[lang = "fn_once_output"]
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ---------------------------------------------------------------------- ///
|
||||||
|
/// All this other stuff needed for core. Unrelated to test.
|
||||||
|
|
||||||
|
#[lang = "destruct"]
|
||||||
|
#[const_trait]
|
||||||
|
trait Destruct {}
|
||||||
|
|
||||||
|
#[lang = "freeze"]
|
||||||
|
unsafe auto trait Freeze {}
|
||||||
|
|
||||||
|
#[lang = "drop"]
|
||||||
|
#[const_trait]
|
||||||
|
trait Drop {
|
||||||
|
fn drop(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
#[lang = "copy"]
|
||||||
|
trait Copy {}
|
||||||
|
|
||||||
|
#[lang = "tuple_trait"]
|
||||||
|
trait Tuple {}
|
||||||
|
|
||||||
|
#[lang = "receiver"]
|
||||||
|
trait Receiver {}
|
||||||
|
|
||||||
|
impl<T: ?Sized> Receiver for &T {}
|
||||||
|
|
||||||
|
impl<T: ?Sized> Receiver for &mut T {}
|
@ -40,7 +40,7 @@ const fn bar() {
|
|||||||
|
|
||||||
#[lang = "Try"]
|
#[lang = "Try"]
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait Try: FromResidual {
|
trait Try: FromResidual<Self::Residual> {
|
||||||
type Output;
|
type Output;
|
||||||
type Residual;
|
type Residual;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ trait Try: FromResidual {
|
|||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
// #[const_trait]
|
// #[const_trait]
|
||||||
trait FromResidual<R = <Self as Try>::Residual> {
|
trait FromResidual<R = <Self as /* FIXME: ~const */ Try>::Residual> {
|
||||||
#[lang = "from_residual"]
|
#[lang = "from_residual"]
|
||||||
fn from_residual(residual: R) -> Self;
|
fn from_residual(residual: R) -> Self;
|
||||||
}
|
}
|
||||||
@ -519,9 +519,14 @@ fn const_eval_select<ARG: Tuple, F, G, RET>(
|
|||||||
called_in_const: F,
|
called_in_const: F,
|
||||||
called_at_rt: G,
|
called_at_rt: G,
|
||||||
) -> RET
|
) -> RET
|
||||||
/* where clauses enforced by built-in method confirmation:
|
|
||||||
where
|
where
|
||||||
F: const FnOnce<Arg, Output = RET>,
|
F: const FnOnce<ARG, Output = RET>,
|
||||||
G: FnOnce<Arg, Output = RET>,
|
G: FnOnce<ARG, Output = RET>;
|
||||||
*/;
|
}
|
||||||
|
|
||||||
|
fn test_const_eval_select() {
|
||||||
|
const fn const_fn() {}
|
||||||
|
fn rt_fn() {}
|
||||||
|
|
||||||
|
unsafe { const_eval_select((), const_fn, rt_fn); }
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
// check-pass
|
// known-bug: #110395
|
||||||
|
// FIXME: effects
|
||||||
|
|
||||||
#![feature(const_trait_impl, effects)]
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
pub trait Owo<X = <Self as Uwu>::T> {}
|
// This fails because `~const Uwu` doesn't imply (non-const) `Uwu`.
|
||||||
|
|
||||||
|
// FIXME: #[const_trait]
|
||||||
|
pub trait Owo<X = <Self as /* FIXME: ~const */ Uwu>::T> {}
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
pub trait Uwu: Owo {
|
pub trait Uwu: Owo {
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
error[E0277]: the trait bound `Self: Uwu` is not satisfied
|
||||||
|
--> $DIR/project.rs:12:1
|
||||||
|
|
|
||||||
|
LL | pub trait Uwu: Owo {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self`
|
||||||
|
|
|
||||||
|
help: consider further restricting `Self`
|
||||||
|
|
|
||||||
|
LL | pub trait Uwu: Owo + Uwu {
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Self: Uwu` is not satisfied
|
||||||
|
--> $DIR/project.rs:12:1
|
||||||
|
|
|
||||||
|
LL | / pub trait Uwu: Owo {
|
||||||
|
LL | | type T;
|
||||||
|
LL | | }
|
||||||
|
| |_^ the trait `Uwu` is not implemented for `Self`
|
||||||
|
|
|
||||||
|
help: consider further restricting `Self`
|
||||||
|
|
|
||||||
|
LL | pub trait Uwu: Owo + Uwu {
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Self: Uwu` is not satisfied
|
||||||
|
--> $DIR/project.rs:12:16
|
||||||
|
|
|
||||||
|
LL | pub trait Uwu: Owo {
|
||||||
|
| ^^^ the trait `Uwu` is not implemented for `Self`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Owo`
|
||||||
|
--> $DIR/project.rs:9:15
|
||||||
|
|
|
||||||
|
LL | pub trait Owo<X = <Self as /* FIXME: ~const */ Uwu>::T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo`
|
||||||
|
help: consider further restricting `Self`
|
||||||
|
|
|
||||||
|
LL | pub trait Uwu: Owo + Uwu {
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Self: Uwu` is not satisfied
|
||||||
|
--> $DIR/project.rs:13:5
|
||||||
|
|
|
||||||
|
LL | type T;
|
||||||
|
| ^^^^^^ the trait `Uwu` is not implemented for `Self`
|
||||||
|
|
|
||||||
|
help: consider further restricting `Self`
|
||||||
|
|
|
||||||
|
LL | pub trait Uwu: Owo + Uwu {
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Self: Uwu` is not satisfied
|
||||||
|
--> $DIR/project.rs:13:5
|
||||||
|
|
|
||||||
|
LL | type T;
|
||||||
|
| ^^^^^^^ the trait `Uwu` is not implemented for `Self`
|
||||||
|
|
|
||||||
|
help: consider further restricting `Self`
|
||||||
|
|
|
||||||
|
LL | pub trait Uwu: Owo + Uwu {
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
@ -1,21 +1,35 @@
|
|||||||
error[E0308]: mismatched types
|
error[E0277]: the trait bound `T: ~const Bar` is not satisfied
|
||||||
--> $DIR/trait-where-clause-const.rs:21:5
|
--> $DIR/trait-where-clause-const.rs:21:5
|
||||||
|
|
|
|
||||||
LL | T::b();
|
LL | T::b();
|
||||||
| ^^^^^^ expected `host`, found `true`
|
| ^ the trait `~const Bar` is not implemented for `T`
|
||||||
|
|
|
|
||||||
= note: expected constant `host`
|
note: required by a bound in `Foo::b`
|
||||||
found constant `true`
|
--> $DIR/trait-where-clause-const.rs:15:24
|
||||||
|
|
|
||||||
|
LL | fn b() where Self: ~const Bar;
|
||||||
|
| ^^^^^^^^^^ required by this bound in `Foo::b`
|
||||||
|
help: consider further restricting this bound
|
||||||
|
|
|
||||||
|
LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
|
||||||
|
| ++++++++++++
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0277]: the trait bound `T: ~const Bar` is not satisfied
|
||||||
--> $DIR/trait-where-clause-const.rs:23:5
|
--> $DIR/trait-where-clause-const.rs:23:12
|
||||||
|
|
|
|
||||||
LL | T::c::<T>();
|
LL | T::c::<T>();
|
||||||
| ^^^^^^^^^^^ expected `host`, found `true`
|
| ^ the trait `~const Bar` is not implemented for `T`
|
||||||
|
|
|
|
||||||
= note: expected constant `host`
|
note: required by a bound in `Foo::c`
|
||||||
found constant `true`
|
--> $DIR/trait-where-clause-const.rs:16:13
|
||||||
|
|
|
||||||
|
LL | fn c<T: ~const Bar>();
|
||||||
|
| ^^^^^^^^^^ required by this bound in `Foo::c`
|
||||||
|
help: consider further restricting this bound
|
||||||
|
|
|
||||||
|
LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
|
||||||
|
| ++++++++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
@ -30,4 +30,4 @@ fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
|||||||
// FIXME(effects): Instead of suggesting `+ const Trait`, suggest
|
// FIXME(effects): Instead of suggesting `+ const Trait`, suggest
|
||||||
// changing `~const Trait` to `const Trait`.
|
// changing `~const Trait` to `const Trait`.
|
||||||
const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||||
//~^ ERROR the trait bound `T: const Trait` is not satisfied
|
//~^ ERROR mismatched types
|
||||||
|
@ -7,16 +7,14 @@ LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
|||||||
= note: expected constant `false`
|
= note: expected constant `false`
|
||||||
found constant `true`
|
found constant `true`
|
||||||
|
|
||||||
error[E0277]: the trait bound `T: const Trait` is not satisfied
|
error[E0308]: mismatched types
|
||||||
--> $DIR/unsatisfied-const-trait-bound.rs:32:50
|
--> $DIR/unsatisfied-const-trait-bound.rs:32:50
|
||||||
|
|
|
|
||||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||||
| ^ the trait `const Trait` is not implemented for `T`
|
| ^^^^^^^^^ expected `false`, found `host`
|
||||||
|
|
|
|
||||||
help: consider further restricting this bound
|
= note: expected constant `false`
|
||||||
|
|
found constant `host`
|
||||||
LL | const fn accept1<T: ~const Trait + const Trait>(_: Container<{ T::make() }>) {}
|
|
||||||
| +++++++++++++
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `Ty: const Trait` is not satisfied
|
error[E0277]: the trait bound `Ty: const Trait` is not satisfied
|
||||||
--> $DIR/unsatisfied-const-trait-bound.rs:20:15
|
--> $DIR/unsatisfied-const-trait-bound.rs:20:15
|
||||||
|
Loading…
Reference in New Issue
Block a user