Skip to content

Commit ab364e2

Browse files
~const trait or projection bounds do not imply non-const bounds
1 parent fde0e98 commit ab364e2

10 files changed

+212
-81
lines changed

compiler/rustc_hir_analysis/src/bounds.rs

-18
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,6 @@ impl<'tcx> Bounds<'tcx> {
4545
polarity: ty::ImplPolarity,
4646
) {
4747
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
48-
49-
// push a non-const (`host = true`) version of the bound if it is `~const`.
50-
if tcx.features().effects
51-
&& let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index
52-
&& trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_
53-
{
54-
let generics = tcx.generics_of(trait_ref.def_id());
55-
let Some(host_index) = generics.host_effect_index else { return };
56-
let trait_ref = trait_ref.map_bound(|mut trait_ref| {
57-
trait_ref.args =
58-
tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| {
59-
if host_index == n { tcx.consts.true_.into() } else { arg }
60-
}));
61-
trait_ref
62-
});
63-
64-
self.push_trait_bound_inner(tcx, trait_ref, span, polarity);
65-
}
6648
}
6749

6850
fn push_trait_bound_inner(

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+6-32
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor};
1111
use rustc_middle::ty::{self, Ty, TyCtxt};
1212
use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate};
1313
use rustc_span::symbol::Ident;
14-
use rustc_span::{sym, Span, DUMMY_SP};
14+
use rustc_span::{Span, DUMMY_SP};
1515

1616
/// Returns a list of all type predicates (explicit and implicit) for the definition with
1717
/// 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
3838
// an obligation and instead be skipped. Otherwise we'd use
3939
// `tcx.def_span(def_id);`
4040
let span = rustc_span::DUMMY_SP;
41-
let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) {
42-
// when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound,
43-
// because only implementing `Self: Trait<.., false>` is currently not possible.
44-
Some((
45-
ty::TraitRef::new(
46-
tcx,
47-
def_id,
48-
ty::GenericArgs::for_item(tcx, def_id, |param, _| {
49-
if param.is_host_effect() {
50-
tcx.consts.true_.into()
51-
} else {
52-
tcx.mk_param_from_def(param)
53-
}
54-
}),
55-
)
56-
.to_predicate(tcx),
41+
42+
result.predicates =
43+
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
44+
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
5745
span,
58-
))
59-
} else {
60-
None
61-
};
62-
result.predicates = tcx.arena.alloc_from_iter(
63-
result
64-
.predicates
65-
.iter()
66-
.copied()
67-
.chain(std::iter::once((
68-
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
69-
span,
70-
)))
71-
.chain(non_const_bound),
72-
);
46+
))));
7347
}
7448
debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
7549
result

tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr

+8-6
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ LL | type Assoc: ~const Foo;
66
|
77
= note: this item cannot have `~const` trait bounds
88

9-
error[E0308]: mismatched types
10-
--> $DIR/assoc-type-const-bound-usage.rs:12:5
9+
error[E0277]: the trait bound `T: Foo` is not satisfied
10+
--> $DIR/assoc-type-const-bound-usage.rs:12:6
1111
|
1212
LL | <T as Foo>::Assoc::foo();
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true`
13+
| ^ the trait `Foo` is not implemented for `T`
1414
|
15-
= note: expected constant `host`
16-
found constant `true`
15+
help: consider further restricting this bound
16+
|
17+
LL | const fn foo<T: ~const Foo + Foo>() {
18+
| +++++
1719

1820
error: aborting due to 2 previous errors
1921

20-
For more information about this error, try `rustc --explain E0308`.
22+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// check-pass
2+
3+
#![crate_type = "lib"]
4+
#![allow(internal_features)]
5+
#![no_std]
6+
#![no_core]
7+
#![feature(
8+
auto_traits,
9+
const_trait_impl,
10+
effects,
11+
lang_items,
12+
no_core,
13+
staged_api,
14+
unboxed_closures
15+
)]
16+
#![stable(feature = "minicore", since = "1.0.0")]
17+
18+
fn test() {
19+
fn is_const_fn<F>(_: F)
20+
where
21+
F: const FnOnce<()>,
22+
{
23+
}
24+
25+
const fn foo() {}
26+
27+
is_const_fn(foo);
28+
}
29+
30+
/// ---------------------------------------------------------------------- ///
31+
/// Const fn trait definitions
32+
33+
#[const_trait]
34+
#[lang = "fn"]
35+
#[rustc_paren_sugar]
36+
trait Fn<Args: Tuple>: ~const FnMut<Args> {
37+
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
38+
}
39+
40+
#[const_trait]
41+
#[lang = "fn_mut"]
42+
#[rustc_paren_sugar]
43+
trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
44+
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
45+
}
46+
47+
#[const_trait]
48+
#[lang = "fn_once"]
49+
#[rustc_paren_sugar]
50+
trait FnOnce<Args: Tuple> {
51+
#[lang = "fn_once_output"]
52+
type Output;
53+
54+
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
55+
}
56+
57+
/// ---------------------------------------------------------------------- ///
58+
/// All this other stuff needed for core. Unrelated to test.
59+
60+
#[lang = "destruct"]
61+
#[const_trait]
62+
trait Destruct {}
63+
64+
#[lang = "freeze"]
65+
unsafe auto trait Freeze {}
66+
67+
#[lang = "drop"]
68+
#[const_trait]
69+
trait Drop {
70+
fn drop(&mut self);
71+
}
72+
73+
#[lang = "sized"]
74+
trait Sized {}
75+
#[lang = "copy"]
76+
trait Copy {}
77+
78+
#[lang = "tuple_trait"]
79+
trait Tuple {}
80+
81+
#[lang = "receiver"]
82+
trait Receiver {}
83+
84+
impl<T: ?Sized> Receiver for &T {}
85+
86+
impl<T: ?Sized> Receiver for &mut T {}

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const fn bar() {
4040

4141
#[lang = "Try"]
4242
#[const_trait]
43-
trait Try: FromResidual {
43+
trait Try: FromResidual<Self::Residual> {
4444
type Output;
4545
type Residual;
4646

@@ -53,7 +53,7 @@ trait Try: FromResidual {
5353

5454
// FIXME
5555
// #[const_trait]
56-
trait FromResidual<R = <Self as Try>::Residual> {
56+
trait FromResidual<R = <Self as /* FIXME: ~const */ Try>::Residual> {
5757
#[lang = "from_residual"]
5858
fn from_residual(residual: R) -> Self;
5959
}
@@ -519,9 +519,14 @@ extern "rust-intrinsic" {
519519
called_in_const: F,
520520
called_at_rt: G,
521521
) -> RET
522-
/* where clauses enforced by built-in method confirmation:
523522
where
524-
F: const FnOnce<Arg, Output = RET>,
525-
G: FnOnce<Arg, Output = RET>,
526-
*/;
523+
F: const FnOnce<ARG, Output = RET>,
524+
G: FnOnce<ARG, Output = RET>;
525+
}
526+
527+
fn test_const_eval_select() {
528+
const fn const_fn() {}
529+
fn rt_fn() {}
530+
531+
unsafe { const_eval_select((), const_fn, rt_fn); }
527532
}

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
// check-pass
1+
// known-bug: #110395
2+
// FIXME: effects
3+
24
#![feature(const_trait_impl, effects)]
35

4-
pub trait Owo<X = <Self as Uwu>::T> {}
6+
// This fails because `~const Uwu` doesn't imply (non-const) `Uwu`.
7+
8+
// FIXME: #[const_trait]
9+
pub trait Owo<X = <Self as /* FIXME: ~const */ Uwu>::T> {}
510

611
#[const_trait]
712
pub trait Uwu: Owo {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
error[E0277]: the trait bound `Self: Uwu` is not satisfied
2+
--> $DIR/project.rs:12:1
3+
|
4+
LL | pub trait Uwu: Owo {
5+
| ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self`
6+
|
7+
help: consider further restricting `Self`
8+
|
9+
LL | pub trait Uwu: Owo + Uwu {
10+
| +++++
11+
12+
error[E0277]: the trait bound `Self: Uwu` is not satisfied
13+
--> $DIR/project.rs:12:1
14+
|
15+
LL | / pub trait Uwu: Owo {
16+
LL | | type T;
17+
LL | | }
18+
| |_^ the trait `Uwu` is not implemented for `Self`
19+
|
20+
help: consider further restricting `Self`
21+
|
22+
LL | pub trait Uwu: Owo + Uwu {
23+
| +++++
24+
25+
error[E0277]: the trait bound `Self: Uwu` is not satisfied
26+
--> $DIR/project.rs:12:16
27+
|
28+
LL | pub trait Uwu: Owo {
29+
| ^^^ the trait `Uwu` is not implemented for `Self`
30+
|
31+
note: required by a bound in `Owo`
32+
--> $DIR/project.rs:9:15
33+
|
34+
LL | pub trait Owo<X = <Self as /* FIXME: ~const */ Uwu>::T> {}
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo`
36+
help: consider further restricting `Self`
37+
|
38+
LL | pub trait Uwu: Owo + Uwu {
39+
| +++++
40+
41+
error[E0277]: the trait bound `Self: Uwu` is not satisfied
42+
--> $DIR/project.rs:13:5
43+
|
44+
LL | type T;
45+
| ^^^^^^ the trait `Uwu` is not implemented for `Self`
46+
|
47+
help: consider further restricting `Self`
48+
|
49+
LL | pub trait Uwu: Owo + Uwu {
50+
| +++++
51+
52+
error[E0277]: the trait bound `Self: Uwu` is not satisfied
53+
--> $DIR/project.rs:13:5
54+
|
55+
LL | type T;
56+
| ^^^^^^^ the trait `Uwu` is not implemented for `Self`
57+
|
58+
help: consider further restricting `Self`
59+
|
60+
LL | pub trait Uwu: Owo + Uwu {
61+
| +++++
62+
63+
error: aborting due to 5 previous errors
64+
65+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
1-
error[E0308]: mismatched types
1+
error[E0277]: the trait bound `T: ~const Bar` is not satisfied
22
--> $DIR/trait-where-clause-const.rs:21:5
33
|
44
LL | T::b();
5-
| ^^^^^^ expected `host`, found `true`
5+
| ^ the trait `~const Bar` is not implemented for `T`
66
|
7-
= note: expected constant `host`
8-
found constant `true`
7+
note: required by a bound in `Foo::b`
8+
--> $DIR/trait-where-clause-const.rs:15:24
9+
|
10+
LL | fn b() where Self: ~const Bar;
11+
| ^^^^^^^^^^ required by this bound in `Foo::b`
12+
help: consider further restricting this bound
13+
|
14+
LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
15+
| ++++++++++++
916

10-
error[E0308]: mismatched types
11-
--> $DIR/trait-where-clause-const.rs:23:5
17+
error[E0277]: the trait bound `T: ~const Bar` is not satisfied
18+
--> $DIR/trait-where-clause-const.rs:23:12
1219
|
1320
LL | T::c::<T>();
14-
| ^^^^^^^^^^^ expected `host`, found `true`
21+
| ^ the trait `~const Bar` is not implemented for `T`
22+
|
23+
note: required by a bound in `Foo::c`
24+
--> $DIR/trait-where-clause-const.rs:16:13
25+
|
26+
LL | fn c<T: ~const Bar>();
27+
| ^^^^^^^^^^ required by this bound in `Foo::c`
28+
help: consider further restricting this bound
1529
|
16-
= note: expected constant `host`
17-
found constant `true`
30+
LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
31+
| ++++++++++++
1832

1933
error: aborting due to 2 previous errors
2034

21-
For more information about this error, try `rustc --explain E0308`.
35+
For more information about this error, try `rustc --explain E0277`.

tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
3030
// FIXME(effects): Instead of suggesting `+ const Trait`, suggest
3131
// changing `~const Trait` to `const Trait`.
3232
const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
33-
//~^ ERROR the trait bound `T: const Trait` is not satisfied
33+
//~^ ERROR mismatched types

tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr

+4-6
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@ LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
77
= note: expected constant `false`
88
found constant `true`
99

10-
error[E0277]: the trait bound `T: const Trait` is not satisfied
10+
error[E0308]: mismatched types
1111
--> $DIR/unsatisfied-const-trait-bound.rs:32:50
1212
|
1313
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
14-
| ^ the trait `const Trait` is not implemented for `T`
15-
|
16-
help: consider further restricting this bound
14+
| ^^^^^^^^^ expected `false`, found `host`
1715
|
18-
LL | const fn accept1<T: ~const Trait + const Trait>(_: Container<{ T::make() }>) {}
19-
| +++++++++++++
16+
= note: expected constant `false`
17+
found constant `host`
2018

2119
error[E0277]: the trait bound `Ty: const Trait` is not satisfied
2220
--> $DIR/unsatisfied-const-trait-bound.rs:20:15

0 commit comments

Comments
 (0)