mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-02 18:27:37 +00:00
Remove PointerLike trait
This commit is contained in:
parent
48aee7e383
commit
e2e3f5809b
@ -6,7 +6,7 @@ use rustc_macros::HashStable_Generic;
|
||||
|
||||
use crate::{
|
||||
AbiAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche,
|
||||
PointeeInfo, Primitive, Scalar, Size, TargetDataLayout, Variants,
|
||||
PointeeInfo, Primitive, Size, Variants,
|
||||
};
|
||||
|
||||
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||
@ -115,16 +115,6 @@ impl<'a> Layout<'a> {
|
||||
pub fn unadjusted_abi_align(self) -> Align {
|
||||
self.0.0.unadjusted_abi_align
|
||||
}
|
||||
|
||||
/// Whether the layout is from a type that implements [`std::marker::PointerLike`].
|
||||
///
|
||||
/// Currently, that means that the type is pointer-sized, pointer-aligned,
|
||||
/// and has a initialized (non-union), scalar ABI.
|
||||
pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool {
|
||||
self.size() == data_layout.pointer_size
|
||||
&& self.align().abi == data_layout.pointer_align.abi
|
||||
&& matches!(self.backend_repr(), BackendRepr::Scalar(Scalar::Initialized { .. }))
|
||||
}
|
||||
}
|
||||
|
||||
/// The layout of a type, alongside the type itself.
|
||||
|
@ -367,8 +367,6 @@ language_item_table! {
|
||||
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
@ -47,7 +47,6 @@ pub(super) fn check_trait<'tcx>(
|
||||
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
|
||||
checker
|
||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
|
||||
checker.check(lang_items.pointer_like(), visit_implementation_of_pointer_like)?;
|
||||
checker.check(
|
||||
lang_items.coerce_pointee_validated_trait(),
|
||||
visit_implementation_of_coerce_pointee_validity,
|
||||
@ -707,104 +706,6 @@ fn infringing_fields_error<'tcx>(
|
||||
err.emit()
|
||||
}
|
||||
|
||||
fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = checker.tcx;
|
||||
let typing_env = ty::TypingEnv::non_body_analysis(tcx, checker.impl_def_id);
|
||||
let impl_span = tcx.def_span(checker.impl_def_id);
|
||||
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
|
||||
|
||||
let is_permitted_primitive = match *self_ty.kind() {
|
||||
ty::Adt(def, _) => def.is_box(),
|
||||
ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if is_permitted_primitive
|
||||
&& let Ok(layout) = tcx.layout_of(typing_env.as_query_input(self_ty))
|
||||
&& layout.layout.is_pointer_like(&tcx.data_layout)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let why_disqualified = match *self_ty.kind() {
|
||||
// If an ADT is repr(transparent)
|
||||
ty::Adt(self_ty_def, args) => {
|
||||
if self_ty_def.repr().transparent() {
|
||||
// FIXME(compiler-errors): This should and could be deduplicated into a query.
|
||||
// Find the nontrivial field.
|
||||
let adt_typing_env = ty::TypingEnv::non_body_analysis(tcx, self_ty_def.did());
|
||||
let nontrivial_field = self_ty_def.all_fields().find(|field_def| {
|
||||
let field_ty = tcx.type_of(field_def.did).instantiate_identity();
|
||||
!tcx.layout_of(adt_typing_env.as_query_input(field_ty))
|
||||
.is_ok_and(|layout| layout.layout.is_1zst())
|
||||
});
|
||||
|
||||
if let Some(nontrivial_field) = nontrivial_field {
|
||||
// Check that the nontrivial field implements `PointerLike`.
|
||||
let nontrivial_field_ty = nontrivial_field.ty(tcx, args);
|
||||
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_bound(
|
||||
ObligationCause::misc(impl_span, checker.impl_def_id),
|
||||
param_env,
|
||||
nontrivial_field_ty,
|
||||
tcx.require_lang_item(LangItem::PointerLike, impl_span),
|
||||
);
|
||||
// FIXME(dyn-star): We should regionck this implementation.
|
||||
if ocx.select_all_or_error().is_empty() {
|
||||
return Ok(());
|
||||
} else {
|
||||
format!(
|
||||
"the field `{field_name}` of {descr} `{self_ty}` \
|
||||
does not implement `PointerLike`",
|
||||
field_name = nontrivial_field.name,
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
format!(
|
||||
"the {descr} `{self_ty}` is `repr(transparent)`, \
|
||||
but does not have a non-trivial field (it is zero-sized)",
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
} else if self_ty_def.is_box() {
|
||||
// If we got here, then the `layout.is_pointer_like()` check failed
|
||||
// and this box is not a thin pointer.
|
||||
|
||||
String::from("boxes of dynamically-sized types are too large to be `PointerLike`")
|
||||
} else {
|
||||
format!(
|
||||
"the {descr} `{self_ty}` is not `repr(transparent)`",
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
}
|
||||
ty::Ref(..) => {
|
||||
// If we got here, then the `layout.is_pointer_like()` check failed
|
||||
// and this reference is not a thin pointer.
|
||||
String::from("references to dynamically-sized types are too large to be `PointerLike`")
|
||||
}
|
||||
ty::Dynamic(..) | ty::Foreign(..) => {
|
||||
String::from("types of dynamic or unknown size may not implement `PointerLike`")
|
||||
}
|
||||
_ => {
|
||||
// This is a white lie; it is true everywhere outside the standard library.
|
||||
format!("only user-defined sized types are eligible for `impl PointerLike`")
|
||||
}
|
||||
};
|
||||
|
||||
Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
impl_span,
|
||||
"implementation must be applied to type that has the same ABI as a pointer, \
|
||||
or is `repr(transparent)` and whose field is `PointerLike`",
|
||||
)
|
||||
.with_note(why_disqualified)
|
||||
.emit())
|
||||
}
|
||||
|
||||
fn visit_implementation_of_coerce_pointee_validity(
|
||||
checker: &Checker<'_>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
|
@ -1149,12 +1149,16 @@ impl<'tcx> TypingEnv<'tcx> {
|
||||
{
|
||||
// FIXME(#132279): We should assert that the value does not contain any placeholders
|
||||
// as these placeholders are also local to the current inference context. However, we
|
||||
// currently use pseudo-canonical queries in the trait solver which replaces params with
|
||||
// placeholders. We should also simply not use pseudo-canonical queries in the trait
|
||||
// solver, at which point we can readd this assert. As of writing this comment, this is
|
||||
// only used by `fn layout_is_pointer_like` when calling `layout_of`.
|
||||
// currently use pseudo-canonical queries in the trait solver, which replaces params
|
||||
// with placeholders during canonicalization. We should also simply not use pseudo-
|
||||
// canonical queries in the trait solver, at which point we can readd this assert.
|
||||
//
|
||||
// debug_assert!(!value.has_placeholders());
|
||||
// As of writing this comment, this is only used when normalizing consts that mention
|
||||
// params.
|
||||
/* debug_assert!(
|
||||
!value.has_placeholders(),
|
||||
"{value:?} which has placeholder shouldn't be pseudo-canonicalized"
|
||||
); */
|
||||
PseudoCanonicalInput { typing_env: self, value }
|
||||
}
|
||||
}
|
||||
|
@ -1623,7 +1623,6 @@ symbols! {
|
||||
pointee_sized,
|
||||
pointee_trait,
|
||||
pointer,
|
||||
pointer_like,
|
||||
poll,
|
||||
poll_next,
|
||||
position,
|
||||
|
@ -14,9 +14,7 @@ use rustc_hir::lang_items::LangItem;
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgsRef, Region, SizedTraitKind, Ty, TyCtxt, Upcast, elaborate,
|
||||
};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Region, SizedTraitKind, Ty, TyCtxt, Upcast};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::DefId;
|
||||
use thin_vec::thin_vec;
|
||||
@ -1147,38 +1145,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
ty::ClauseKind::TypeOutlives(outlives).upcast(tcx),
|
||||
));
|
||||
|
||||
// Require that all AFIT will return something that can be coerced into `dyn*`
|
||||
// -- a shim will be responsible for doing the actual coercion to `dyn*`.
|
||||
if let Some(principal) = data.principal() {
|
||||
for supertrait in
|
||||
elaborate::supertraits(tcx, principal.with_self_ty(tcx, source))
|
||||
{
|
||||
if tcx.is_trait_alias(supertrait.def_id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for &assoc_item in tcx.associated_item_def_ids(supertrait.def_id()) {
|
||||
if !tcx.is_impl_trait_in_trait(assoc_item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// RPITITs with `Self: Sized` don't need to be checked.
|
||||
if tcx.generics_require_sized_self(assoc_item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let pointer_like_goal = pointer_like_goal_for_rpitit(
|
||||
tcx,
|
||||
supertrait,
|
||||
assoc_item,
|
||||
&obligation.cause,
|
||||
);
|
||||
|
||||
nested.push(predicate_to_obligation(pointer_like_goal.upcast(tcx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImplSource::Builtin(BuiltinImplSource::Misc, nested)
|
||||
}
|
||||
|
||||
@ -1344,46 +1310,3 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures)
|
||||
/// implements the `PointerLike` trait, which is a requirement for the RPITIT to be
|
||||
/// coercible to `dyn* Future`, which is itself a requirement for the RPITIT's parent
|
||||
/// trait to be coercible to `dyn Trait`.
|
||||
///
|
||||
/// We do this given a supertrait's substitutions, and then augment the substitutions
|
||||
/// with bound variables to compute the goal universally. Given that `PointerLike` has
|
||||
/// no region requirements (at least for the built-in pointer types), this shouldn't
|
||||
/// *really* matter, but it is the best choice for soundness.
|
||||
fn pointer_like_goal_for_rpitit<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
supertrait: ty::PolyTraitRef<'tcx>,
|
||||
rpitit_item: DefId,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) -> ty::PolyTraitRef<'tcx> {
|
||||
let mut bound_vars = supertrait.bound_vars().to_vec();
|
||||
|
||||
let args = supertrait.skip_binder().args.extend_to(tcx, rpitit_item, |arg, _| match arg.kind {
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
let kind = ty::BoundRegionKind::Named(arg.def_id, tcx.item_name(arg.def_id));
|
||||
bound_vars.push(ty::BoundVariableKind::Region(kind));
|
||||
ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
|
||||
)
|
||||
.into()
|
||||
}
|
||||
ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Const { .. } => {
|
||||
unreachable!()
|
||||
}
|
||||
});
|
||||
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::PointerLike, cause.span),
|
||||
[Ty::new_projection_from_args(tcx, rpitit_item, args)],
|
||||
),
|
||||
tcx.mk_bound_variable_kinds(&bound_vars),
|
||||
)
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ use core::error::{self, Error};
|
||||
use core::fmt;
|
||||
use core::future::Future;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::marker::{PointerLike, Tuple, Unsize};
|
||||
use core::marker::{Tuple, Unsize};
|
||||
use core::mem::{self, SizedTypeProperties};
|
||||
use core::ops::{
|
||||
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut,
|
||||
@ -2132,6 +2132,3 @@ impl<E: Error> Error for Box<E> {
|
||||
Error::provide(&**self, request);
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T> PointerLike for Box<T> {}
|
||||
|
@ -134,7 +134,6 @@
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pin_coerce_unsized_trait)]
|
||||
#![feature(pointer_like_trait)]
|
||||
#![feature(ptr_alignment_type)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(ptr_metadata)]
|
||||
|
@ -252,7 +252,7 @@
|
||||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt::{self, Debug, Display};
|
||||
use crate::marker::{PhantomData, PointerLike, Unsize};
|
||||
use crate::marker::{PhantomData, Unsize};
|
||||
use crate::mem;
|
||||
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
|
||||
use crate::panic::const_panic;
|
||||
@ -669,9 +669,6 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
|
||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Cell<U>> for Cell<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T: PointerLike> PointerLike for Cell<T> {}
|
||||
|
||||
impl<T> Cell<[T]> {
|
||||
/// Returns a `&[Cell<T>]` from a `&Cell<[T]>`
|
||||
///
|
||||
@ -2361,9 +2358,6 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafeCell<U>> for UnsafeCell<T> {}
|
||||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T: PointerLike> PointerLike for UnsafeCell<T> {}
|
||||
|
||||
/// [`UnsafeCell`], but [`Sync`].
|
||||
///
|
||||
/// This is just an `UnsafeCell`, except it implements `Sync`
|
||||
@ -2470,9 +2464,6 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<SyncUnsafeCell<U>> for SyncUnsafeCell
|
||||
//#[unstable(feature = "sync_unsafe_cell", issue = "95439")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T: PointerLike> PointerLike for SyncUnsafeCell<T> {}
|
||||
|
||||
#[allow(unused)]
|
||||
fn assert_coerce_unsized(
|
||||
a: UnsafeCell<&i32>,
|
||||
|
@ -1066,37 +1066,6 @@ pub trait Destruct {}
|
||||
#[rustc_do_not_implement_via_object]
|
||||
pub trait Tuple {}
|
||||
|
||||
/// A marker for pointer-like types.
|
||||
///
|
||||
/// This trait can only be implemented for types that are certain to have
|
||||
/// the same size and alignment as a [`usize`] or [`*const ()`](pointer).
|
||||
/// To ensure this, there are special requirements on implementations
|
||||
/// of `PointerLike` (other than the already-provided implementations
|
||||
/// for built-in types):
|
||||
///
|
||||
/// * The type must have `#[repr(transparent)]`.
|
||||
/// * The type’s sole non-zero-sized field must itself implement `PointerLike`.
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
#[lang = "pointer_like"]
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "`{Self}` needs to have the same ABI as a pointer",
|
||||
label = "`{Self}` needs to be a pointer-like type"
|
||||
)]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
pub trait PointerLike {}
|
||||
|
||||
marker_impls! {
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
PointerLike for
|
||||
isize,
|
||||
usize,
|
||||
{T} &T,
|
||||
{T} &mut T,
|
||||
{T} *const T,
|
||||
{T} *mut T,
|
||||
{T: PointerLike} crate::pin::Pin<T>,
|
||||
}
|
||||
|
||||
/// A marker for types which can be used as types of `const` generic parameters.
|
||||
///
|
||||
/// These types must have a proper equivalence relation (`Eq`) and it must be automatically
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::marker::{PointerLike, Unpin};
|
||||
use crate::marker::Unpin;
|
||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||
use crate::pin::Pin;
|
||||
use crate::{fmt, ptr};
|
||||
@ -178,8 +178,4 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafePinned<U>> for UnsafePinned<T>
|
||||
// #[unstable(feature = "unsafe_pinned", issue = "125735")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafePinned<U>> for UnsafePinned<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
// #[unstable(feature = "unsafe_pinned", issue = "125735")]
|
||||
impl<T: PointerLike> PointerLike for UnsafePinned<T> {}
|
||||
|
||||
// FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned<T>?
|
||||
|
@ -1628,9 +1628,6 @@ impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
unsafe impl<T: PointeeSized> PinCoerceUnsized for NonNull<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T> core::marker::PointerLike for NonNull<T> {}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: PointeeSized> fmt::Debug for NonNull<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -1,14 +0,0 @@
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
#![feature(pointer_like_trait)]
|
||||
|
||||
use std::marker::PointerLike;
|
||||
|
||||
fn require_(_: impl PointerLike) {}
|
||||
|
||||
fn main() {
|
||||
require_(1usize);
|
||||
require_(1u16);
|
||||
//~^ ERROR `u16` needs to have the same ABI as a pointer
|
||||
require_(&1i16);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
error[E0277]: `u16` needs to have the same ABI as a pointer
|
||||
--> $DIR/pointer-like.rs:11:14
|
||||
|
|
||||
LL | require_(1u16);
|
||||
| -------- ^^^^ the trait `PointerLike` is not implemented for `u16`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: the trait bound `u16: PointerLike` is not satisfied
|
||||
note: required by a bound in `require_`
|
||||
--> $DIR/pointer-like.rs:7:21
|
||||
|
|
||||
LL | fn require_(_: impl PointerLike) {}
|
||||
| ^^^^^^^^^^^ required by this bound in `require_`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | require_(&1u16);
|
||||
| +
|
||||
LL | require_(&mut 1u16);
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
x
Reference in New Issue
Block a user