Skip to content

Commit

Permalink
Rollup merge of #99704 - fee1-dead-contrib:add_self_tilde_const_trait…
Browse files Browse the repository at this point in the history
…, r=oli-obk

Add `Self: ~const Trait` to traits with `#[const_trait]`

r? `@oli-obk`
  • Loading branch information
JohnTitor authored Jul 27, 2022
2 parents 3b780fc + 4b7a348 commit 28b44ff
Show file tree
Hide file tree
Showing 30 changed files with 199 additions and 209 deletions.
8 changes: 4 additions & 4 deletions compiler/rustc_const_eval/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use rustc_trait_selection::traits::SelectionContext;

use super::ConstCx;
use crate::errors::{
MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrComparisonErr, RawPtrToIntErr,
StaticAccessErr, TransientMutBorrowErr, TransientMutBorrowErrRaw,
MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
TransientMutBorrowErr, TransientMutBorrowErrRaw,
};
use crate::util::{call_kind, CallDesugaringKind, CallKind};

Expand Down Expand Up @@ -654,10 +654,10 @@ pub struct RawPtrComparison;
impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
_: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
ccx.tcx.sess.create_err(RawPtrComparisonErr { span })
span_bug!(span, "raw ptr comparison should already be caught in the trait system");
}
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,14 @@ impl<'tcx> TraitPredicate<'tcx> {
pub fn is_const_if_const(self) -> bool {
self.constness == BoundConstness::ConstIfConst
}

pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
match (self.constness, constness) {
(BoundConstness::NotConst, _)
| (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
(BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
}
}
}

impl<'tcx> PolyTraitPredicate<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2556,7 +2556,7 @@ define_print_and_forward_display! {

ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), ": ");
if let ty::BoundConstness::ConstIfConst = self.constness {
if let ty::BoundConstness::ConstIfConst = self.constness && cx.tcx().features().const_trait_impl {
p!("~const ");
}
p!(print(self.trait_ref.print_only_trait_path()))
Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
);
} else if !suggested {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
Expand Down Expand Up @@ -701,7 +701,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
{
let trait_ref = trait_pred.to_poly_trait_ref();
let impl_candidates =
self.find_similar_impl_candidates(trait_ref);
self.find_similar_impl_candidates(trait_pred);
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
Expand Down Expand Up @@ -1325,7 +1325,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {

fn find_similar_impl_candidates(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Vec<ImplCandidate<'tcx>>;

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

fn find_similar_impl_candidates(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Vec<ImplCandidate<'tcx>> {
self.tcx
.all_impls(trait_ref.def_id())
.all_impls(trait_pred.def_id())
.filter_map(|def_id| {
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
|| !trait_pred
.skip_binder()
.is_constness_satisfied_by(self.tcx.constness(def_id))
{
return None;
}

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

self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty(), false)
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
.map(|similarity| ImplCandidate { trait_ref: imp, similarity })
})
.collect()
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2090,10 +2090,17 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
// from the trait itself that *shouldn't* be shown as the source of
// an obligation and instead be skipped. Otherwise we'd use
// `tcx.def_span(def_id);`

let constness = if tcx.has_attr(def_id, sym::const_trait) {
ty::BoundConstness::ConstIfConst
} else {
ty::BoundConstness::NotConst
};

let span = rustc_span::DUMMY_SP;
result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx),
ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx),
span,
))));
}
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1503,9 +1503,10 @@ mod impls {
// & pointers

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
impl<A: ?Sized, B: ?Sized> const PartialEq<&B> for &A
where
A: PartialEq<B>,
A: ~const PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&B) -> bool {
Expand Down
6 changes: 2 additions & 4 deletions src/test/ui/const-generics/issues/issue-90318.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ impl True for If<true> {}
fn consume<T: 'static>(_val: T)
where
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
//~^ ERROR: overly complex generic constant
//~| ERROR: cannot call non-const operator in constants
//~^ ERROR: can't compare
{
}

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

Expand Down
56 changes: 16 additions & 40 deletions src/test/ui/const-generics/issues/issue-90318.stderr
Original file line number Diff line number Diff line change
@@ -1,53 +1,29 @@
error: overly complex generic constant
--> $DIR/issue-90318.rs:14:8
error[E0277]: can't compare `TypeId` with `_` in const contexts
--> $DIR/issue-90318.rs:14:28
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| borrowing is not supported in generic constants
| ^^ no implementation for `TypeId == _`
|
= help: consider moving this anonymous constant into a `const` function
= note: this operation may be supported in the future

error[E0015]: cannot call non-const operator in constants
--> $DIR/issue-90318.rs:14:10
= help: the trait `~const PartialEq<_>` is not implemented for `TypeId`
note: the trait `PartialEq<_>` is implemented for `TypeId`, but that implementation is not `const`
--> $DIR/issue-90318.rs:14:28
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
|
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
| ^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
| ^^

error: overly complex generic constant
--> $DIR/issue-90318.rs:22:8
error[E0277]: can't compare `TypeId` with `_` in const contexts
--> $DIR/issue-90318.rs:21:28
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| borrowing is not supported in generic constants
| ^^ no implementation for `TypeId == _`
|
= help: consider moving this anonymous constant into a `const` function
= note: this operation may be supported in the future

error[E0015]: cannot call non-const operator in constants
--> $DIR/issue-90318.rs:22:10
= help: the trait `~const PartialEq<_>` is not implemented for `TypeId`
note: the trait `PartialEq<_>` is implemented for `TypeId`, but that implementation is not `const`
--> $DIR/issue-90318.rs:21:28
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
|
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
| ^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
| ^^

error: aborting due to 4 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0277`.
4 changes: 2 additions & 2 deletions src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
fn main() {}

// unconst and bad, will thus error in miri
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR can't compare
// unconst and bad, will thus error in miri
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR can't compare
47 changes: 39 additions & 8 deletions src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
error: pointers cannot be reliably compared during const eval
--> $DIR/const_raw_ptr_ops.rs:4:26
error[E0277]: can't compare `*const i32` with `_` in const contexts
--> $DIR/const_raw_ptr_ops.rs:4:43
|
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^ no implementation for `*const i32 == _`
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
= help: the trait `~const PartialEq<_>` is not implemented for `*const i32`
note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const`
--> $DIR/const_raw_ptr_ops.rs:4:43
|
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
| ^^
= help: the following other types implement trait `PartialEq<Rhs>`:
f32
f64
i128
i16
i32
i64
i8
isize
and 6 others

error: pointers cannot be reliably compared during const eval
--> $DIR/const_raw_ptr_ops.rs:6:27
error[E0277]: can't compare `*const i32` with `_` in const contexts
--> $DIR/const_raw_ptr_ops.rs:6:44
|
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^ no implementation for `*const i32 == _`
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
= help: the trait `~const PartialEq<_>` is not implemented for `*const i32`
note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const`
--> $DIR/const_raw_ptr_ops.rs:6:44
|
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
| ^^
= help: the following other types implement trait `PartialEq<Rhs>`:
f32
f64
i128
i16
i32
i64
i8
isize
and 6 others

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
2 changes: 1 addition & 1 deletion src/test/ui/consts/issue-25826.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
fn id<T>(t: T) -> T { t }
fn main() {
const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
//~^ ERROR pointers cannot be reliably compared during const eval
//~^ ERROR can't compare
println!("{}", A);
}
18 changes: 14 additions & 4 deletions src/test/ui/consts/issue-25826.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
error: pointers cannot be reliably compared during const eval
--> $DIR/issue-25826.rs:3:30
error[E0277]: can't compare `*const ()` with `*const ()` in const contexts
--> $DIR/issue-25826.rs:3:52
|
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^ no implementation for `*const () < *const ()` and `*const () > *const ()`
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
= help: the trait `~const PartialOrd` is not implemented for `*const ()`
note: the trait `PartialOrd` is implemented for `*const ()`, but that implementation is not `const`
--> $DIR/issue-25826.rs:3:52
|
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
| ^
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | fn main() where *const (): ~const PartialOrd {
| ++++++++++++++++++++++++++++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
2 changes: 1 addition & 1 deletion src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const fn cmp(x: fn(), y: fn()) -> bool {
unsafe { x == y }
//~^ ERROR pointers cannot be reliably compared
//~^ ERROR can't compare
}

fn main() {}
14 changes: 10 additions & 4 deletions src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
error: pointers cannot be reliably compared during const eval
--> $DIR/cmp_fn_pointers.rs:2:14
error[E0277]: can't compare `fn()` with `_` in const contexts
--> $DIR/cmp_fn_pointers.rs:2:16
|
LL | unsafe { x == y }
| ^^^^^^
| ^^ no implementation for `fn() == _`
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
= help: the trait `~const PartialEq<_>` is not implemented for `fn()`
note: the trait `PartialEq<_>` is implemented for `fn()`, but that implementation is not `const`
--> $DIR/cmp_fn_pointers.rs:2:16
|
LL | unsafe { x == y }
| ^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
10 changes: 2 additions & 8 deletions src/test/ui/consts/miri_unleashed/ptr_arith.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@
#![feature(core_intrinsics)]
#![allow(const_err)]

// During CTFE, we prevent pointer comparison and pointer-to-int casts.

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

static PTR_INT_CAST: () = {
let x = &0 as *const _ as usize;
Expand Down
Loading

0 comments on commit 28b44ff

Please sign in to comment.