Skip to content

Commit 28b44ff

Browse files
authored
Rollup merge of rust-lang#99704 - fee1-dead-contrib:add_self_tilde_const_trait, r=oli-obk
Add `Self: ~const Trait` to traits with `#[const_trait]` r? `@oli-obk`
2 parents 3b780fc + 4b7a348 commit 28b44ff

30 files changed

+199
-209
lines changed

compiler/rustc_const_eval/src/transform/check_consts/ops.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use rustc_trait_selection::traits::SelectionContext;
2323

2424
use super::ConstCx;
2525
use crate::errors::{
26-
MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrComparisonErr, RawPtrToIntErr,
27-
StaticAccessErr, TransientMutBorrowErr, TransientMutBorrowErrRaw,
26+
MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
27+
TransientMutBorrowErr, TransientMutBorrowErrRaw,
2828
};
2929
use crate::util::{call_kind, CallDesugaringKind, CallKind};
3030

@@ -654,10 +654,10 @@ pub struct RawPtrComparison;
654654
impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
655655
fn build_error(
656656
&self,
657-
ccx: &ConstCx<'_, 'tcx>,
657+
_: &ConstCx<'_, 'tcx>,
658658
span: Span,
659659
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
660-
ccx.tcx.sess.create_err(RawPtrComparisonErr { span })
660+
span_bug!(span, "raw ptr comparison should already be caught in the trait system");
661661
}
662662
}
663663

compiler/rustc_middle/src/ty/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,14 @@ impl<'tcx> TraitPredicate<'tcx> {
829829
pub fn is_const_if_const(self) -> bool {
830830
self.constness == BoundConstness::ConstIfConst
831831
}
832+
833+
pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
834+
match (self.constness, constness) {
835+
(BoundConstness::NotConst, _)
836+
| (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
837+
(BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
838+
}
839+
}
832840
}
833841

834842
impl<'tcx> PolyTraitPredicate<'tcx> {

compiler/rustc_middle/src/ty/print/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2556,7 +2556,7 @@ define_print_and_forward_display! {
25562556

25572557
ty::TraitPredicate<'tcx> {
25582558
p!(print(self.trait_ref.self_ty()), ": ");
2559-
if let ty::BoundConstness::ConstIfConst = self.constness {
2559+
if let ty::BoundConstness::ConstIfConst = self.constness && cx.tcx().features().const_trait_impl {
25602560
p!("~const ");
25612561
}
25622562
p!(print(self.trait_ref.print_only_trait_path()))

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
666666
);
667667
} else if !suggested {
668668
// Can't show anything else useful, try to find similar impls.
669-
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
669+
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
670670
if !self.report_similar_impl_candidates(
671671
impl_candidates,
672672
trait_ref,
@@ -701,7 +701,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
701701
{
702702
let trait_ref = trait_pred.to_poly_trait_ref();
703703
let impl_candidates =
704-
self.find_similar_impl_candidates(trait_ref);
704+
self.find_similar_impl_candidates(trait_pred);
705705
self.report_similar_impl_candidates(
706706
impl_candidates,
707707
trait_ref,
@@ -1325,7 +1325,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
13251325

13261326
fn find_similar_impl_candidates(
13271327
&self,
1328-
trait_ref: ty::PolyTraitRef<'tcx>,
1328+
trait_pred: ty::PolyTraitPredicate<'tcx>,
13291329
) -> Vec<ImplCandidate<'tcx>>;
13301330

13311331
fn report_similar_impl_candidates(
@@ -1694,18 +1694,22 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
16941694

16951695
fn find_similar_impl_candidates(
16961696
&self,
1697-
trait_ref: ty::PolyTraitRef<'tcx>,
1697+
trait_pred: ty::PolyTraitPredicate<'tcx>,
16981698
) -> Vec<ImplCandidate<'tcx>> {
16991699
self.tcx
1700-
.all_impls(trait_ref.def_id())
1700+
.all_impls(trait_pred.def_id())
17011701
.filter_map(|def_id| {
1702-
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
1702+
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
1703+
|| !trait_pred
1704+
.skip_binder()
1705+
.is_constness_satisfied_by(self.tcx.constness(def_id))
1706+
{
17031707
return None;
17041708
}
17051709

17061710
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
17071711

1708-
self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty(), false)
1712+
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
17091713
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
17101714
})
17111715
.collect()

compiler/rustc_typeck/src/collect.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -2090,10 +2090,17 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
20902090
// from the trait itself that *shouldn't* be shown as the source of
20912091
// an obligation and instead be skipped. Otherwise we'd use
20922092
// `tcx.def_span(def_id);`
2093+
2094+
let constness = if tcx.has_attr(def_id, sym::const_trait) {
2095+
ty::BoundConstness::ConstIfConst
2096+
} else {
2097+
ty::BoundConstness::NotConst
2098+
};
2099+
20932100
let span = rustc_span::DUMMY_SP;
20942101
result.predicates =
20952102
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
2096-
ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx),
2103+
ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx),
20972104
span,
20982105
))));
20992106
}

library/core/src/cmp.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1503,9 +1503,10 @@ mod impls {
15031503
// & pointers
15041504

15051505
#[stable(feature = "rust1", since = "1.0.0")]
1506-
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
1506+
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
1507+
impl<A: ?Sized, B: ?Sized> const PartialEq<&B> for &A
15071508
where
1508-
A: PartialEq<B>,
1509+
A: ~const PartialEq<B>,
15091510
{
15101511
#[inline]
15111512
fn eq(&self, other: &&B) -> bool {

src/test/ui/const-generics/issues/issue-90318.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,14 @@ impl True for If<true> {}
1212
fn consume<T: 'static>(_val: T)
1313
where
1414
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
15-
//~^ ERROR: overly complex generic constant
16-
//~| ERROR: cannot call non-const operator in constants
15+
//~^ ERROR: can't compare
1716
{
1817
}
1918

2019
fn test<T: 'static>()
2120
where
2221
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
23-
//~^ ERROR: overly complex generic constant
24-
//~| ERROR: cannot call non-const operator in constants
22+
//~^ ERROR: can't compare
2523
{
2624
}
2725

Original file line numberDiff line numberDiff line change
@@ -1,53 +1,29 @@
1-
error: overly complex generic constant
2-
--> $DIR/issue-90318.rs:14:8
1+
error[E0277]: can't compare `TypeId` with `_` in const contexts
2+
--> $DIR/issue-90318.rs:14:28
33
|
44
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
5-
| ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
6-
| |
7-
| borrowing is not supported in generic constants
5+
| ^^ no implementation for `TypeId == _`
86
|
9-
= help: consider moving this anonymous constant into a `const` function
10-
= note: this operation may be supported in the future
11-
12-
error[E0015]: cannot call non-const operator in constants
13-
--> $DIR/issue-90318.rs:14:10
7+
= help: the trait `~const PartialEq<_>` is not implemented for `TypeId`
8+
note: the trait `PartialEq<_>` is implemented for `TypeId`, but that implementation is not `const`
9+
--> $DIR/issue-90318.rs:14:28
1410
|
1511
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17-
|
18-
note: impl defined here, but it is not `const`
19-
--> $SRC_DIR/core/src/any.rs:LL:COL
20-
|
21-
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
22-
| ^^^^^^^^^
23-
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
24-
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
12+
| ^^
2513

26-
error: overly complex generic constant
27-
--> $DIR/issue-90318.rs:22:8
14+
error[E0277]: can't compare `TypeId` with `_` in const contexts
15+
--> $DIR/issue-90318.rs:21:28
2816
|
2917
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
30-
| ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
31-
| |
32-
| borrowing is not supported in generic constants
18+
| ^^ no implementation for `TypeId == _`
3319
|
34-
= help: consider moving this anonymous constant into a `const` function
35-
= note: this operation may be supported in the future
36-
37-
error[E0015]: cannot call non-const operator in constants
38-
--> $DIR/issue-90318.rs:22:10
20+
= help: the trait `~const PartialEq<_>` is not implemented for `TypeId`
21+
note: the trait `PartialEq<_>` is implemented for `TypeId`, but that implementation is not `const`
22+
--> $DIR/issue-90318.rs:21:28
3923
|
4024
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42-
|
43-
note: impl defined here, but it is not `const`
44-
--> $SRC_DIR/core/src/any.rs:LL:COL
45-
|
46-
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
47-
| ^^^^^^^^^
48-
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
49-
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
25+
| ^^
5026

51-
error: aborting due to 4 previous errors
27+
error: aborting due to 2 previous errors
5228

53-
For more information about this error, try `rustc --explain E0015`.
29+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn main() {}
22

33
// unconst and bad, will thus error in miri
4-
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably
4+
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR can't compare
55
// unconst and bad, will thus error in miri
6-
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably
6+
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR can't compare
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,49 @@
1-
error: pointers cannot be reliably compared during const eval
2-
--> $DIR/const_raw_ptr_ops.rs:4:26
1+
error[E0277]: can't compare `*const i32` with `_` in const contexts
2+
--> $DIR/const_raw_ptr_ops.rs:4:43
33
|
44
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^ no implementation for `*const i32 == _`
66
|
7-
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
7+
= help: the trait `~const PartialEq<_>` is not implemented for `*const i32`
8+
note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const`
9+
--> $DIR/const_raw_ptr_ops.rs:4:43
10+
|
11+
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
12+
| ^^
13+
= help: the following other types implement trait `PartialEq<Rhs>`:
14+
f32
15+
f64
16+
i128
17+
i16
18+
i32
19+
i64
20+
i8
21+
isize
22+
and 6 others
823

9-
error: pointers cannot be reliably compared during const eval
10-
--> $DIR/const_raw_ptr_ops.rs:6:27
24+
error[E0277]: can't compare `*const i32` with `_` in const contexts
25+
--> $DIR/const_raw_ptr_ops.rs:6:44
1126
|
1227
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28+
| ^^ no implementation for `*const i32 == _`
1429
|
15-
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
30+
= help: the trait `~const PartialEq<_>` is not implemented for `*const i32`
31+
note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const`
32+
--> $DIR/const_raw_ptr_ops.rs:6:44
33+
|
34+
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
35+
| ^^
36+
= help: the following other types implement trait `PartialEq<Rhs>`:
37+
f32
38+
f64
39+
i128
40+
i16
41+
i32
42+
i64
43+
i8
44+
isize
45+
and 6 others
1646

1747
error: aborting due to 2 previous errors
1848

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

src/test/ui/consts/issue-25826.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn id<T>(t: T) -> T { t }
22
fn main() {
33
const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
4-
//~^ ERROR pointers cannot be reliably compared during const eval
4+
//~^ ERROR can't compare
55
println!("{}", A);
66
}

src/test/ui/consts/issue-25826.stderr

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
error: pointers cannot be reliably compared during const eval
2-
--> $DIR/issue-25826.rs:3:30
1+
error[E0277]: can't compare `*const ()` with `*const ()` in const contexts
2+
--> $DIR/issue-25826.rs:3:52
33
|
44
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^ no implementation for `*const () < *const ()` and `*const () > *const ()`
66
|
7-
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
7+
= help: the trait `~const PartialOrd` is not implemented for `*const ()`
8+
note: the trait `PartialOrd` is implemented for `*const ()`, but that implementation is not `const`
9+
--> $DIR/issue-25826.rs:3:52
10+
|
11+
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
12+
| ^
13+
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
14+
|
15+
LL | fn main() where *const (): ~const PartialOrd {
16+
| ++++++++++++++++++++++++++++++++++
817

918
error: aborting due to previous error
1019

20+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const fn cmp(x: fn(), y: fn()) -> bool {
22
unsafe { x == y }
3-
//~^ ERROR pointers cannot be reliably compared
3+
//~^ ERROR can't compare
44
}
55

66
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
error: pointers cannot be reliably compared during const eval
2-
--> $DIR/cmp_fn_pointers.rs:2:14
1+
error[E0277]: can't compare `fn()` with `_` in const contexts
2+
--> $DIR/cmp_fn_pointers.rs:2:16
33
|
44
LL | unsafe { x == y }
5-
| ^^^^^^
5+
| ^^ no implementation for `fn() == _`
66
|
7-
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
7+
= help: the trait `~const PartialEq<_>` is not implemented for `fn()`
8+
note: the trait `PartialEq<_>` is implemented for `fn()`, but that implementation is not `const`
9+
--> $DIR/cmp_fn_pointers.rs:2:16
10+
|
11+
LL | unsafe { x == y }
12+
| ^^
813

914
error: aborting due to previous error
1015

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

src/test/ui/consts/miri_unleashed/ptr_arith.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,8 @@
22
#![feature(core_intrinsics)]
33
#![allow(const_err)]
44

5-
// During CTFE, we prevent pointer comparison and pointer-to-int casts.
6-
7-
static CMP: () = {
8-
let x = &0 as *const _;
9-
let _v = x == x;
10-
//~^ ERROR could not evaluate static initializer
11-
//~| "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
12-
};
5+
// During CTFE, we prevent pointer-to-int casts.
6+
// Pointer comparisons are prevented in the trait system.
137

148
static PTR_INT_CAST: () = {
159
let x = &0 as *const _ as usize;

0 commit comments

Comments
 (0)