mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 14:23:45 +00:00
Make PointerLike opt-in as a trait
This commit is contained in:
parent
06e66d78c3
commit
228068bc6e
@ -37,22 +37,19 @@ pub(super) fn check_trait<'tcx>(
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let lang_items = tcx.lang_items();
|
||||
let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
|
||||
let mut res = checker.check(lang_items.drop_trait(), visit_implementation_of_drop);
|
||||
res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy));
|
||||
res = res.and(checker.check(lang_items.const_param_ty_trait(), |checker| {
|
||||
checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
|
||||
checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
|
||||
checker.check(lang_items.const_param_ty_trait(), |checker| {
|
||||
visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
|
||||
}));
|
||||
res = res.and(checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
|
||||
})?;
|
||||
checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
|
||||
visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
|
||||
}));
|
||||
|
||||
res = res.and(
|
||||
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized),
|
||||
);
|
||||
res.and(
|
||||
checker
|
||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn),
|
||||
)
|
||||
})?;
|
||||
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)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Checker<'tcx> {
|
||||
@ -663,3 +660,63 @@ 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();
|
||||
|
||||
// If an ADT is repr(transparent)...
|
||||
if let ty::Adt(def, args) = *self_ty.kind()
|
||||
&& 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, def.did());
|
||||
let nontrivial_field = 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 = 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,
|
||||
tcx.lang_items().pointer_like().unwrap(),
|
||||
);
|
||||
// FIXME(dyn-star): We should regionck this implementation.
|
||||
if ocx.select_all_or_error().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(());
|
||||
}
|
||||
|
||||
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`",
|
||||
)
|
||||
.emit())
|
||||
}
|
||||
|
@ -191,6 +191,8 @@ use core::error::{self, Error};
|
||||
use core::fmt;
|
||||
use core::future::Future;
|
||||
use core::hash::{Hash, Hasher};
|
||||
#[cfg(not(bootstrap))]
|
||||
use core::marker::PointerLike;
|
||||
use core::marker::{Tuple, Unsize};
|
||||
use core::mem::{self, SizedTypeProperties};
|
||||
use core::ops::{
|
||||
@ -2131,3 +2133,7 @@ impl<E: Error> Error for Box<E> {
|
||||
Error::provide(&**self, request);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T> PointerLike for Box<T> {}
|
||||
|
@ -136,6 +136,7 @@
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pin_coerce_unsized_trait)]
|
||||
#![feature(pointer_like_trait)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(ptr_sub_ptr)]
|
||||
|
@ -981,6 +981,18 @@ pub trait Tuple {}
|
||||
)]
|
||||
pub trait PointerLike {}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
marker_impls! {
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
PointerLike for
|
||||
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,16 +0,0 @@
|
||||
//@ known-bug: #113280
|
||||
//@ only-x86_64
|
||||
|
||||
#![feature(dyn_star, pointer_like_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PointerLike;
|
||||
|
||||
fn make_dyn_star<'a>(t: impl PointerLike + Debug + 'a) -> dyn* Debug + 'a {
|
||||
f32::from_bits(0x1) as f64
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", make_dyn_star(Box::new(1i32)));
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
//@ known-bug: #127676
|
||||
//@ edition:2018
|
||||
|
||||
#![feature(dyn_star,const_async_blocks)]
|
||||
|
||||
static S: dyn* Send + Sync = async { 42 };
|
||||
|
||||
pub fn main() {}
|
9
tests/ui/dyn-star/async-block-dyn-star.rs
Normal file
9
tests/ui/dyn-star/async-block-dyn-star.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ edition:2018
|
||||
|
||||
#![feature(dyn_star, const_async_blocks)]
|
||||
//~^ WARN the feature `dyn_star` is incomplete
|
||||
|
||||
static S: dyn* Send + Sync = async { 42 };
|
||||
//~^ needs to have the same ABI as a pointer
|
||||
|
||||
pub fn main() {}
|
20
tests/ui/dyn-star/async-block-dyn-star.stderr
Normal file
20
tests/ui/dyn-star/async-block-dyn-star.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/async-block-dyn-star.rs:3:12
|
||||
|
|
||||
LL | #![feature(dyn_star, const_async_blocks)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0277]: `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}` needs to have the same ABI as a pointer
|
||||
--> $DIR/async-block-dyn-star.rs:6:30
|
||||
|
|
||||
LL | static S: dyn* Send + Sync = async { 42 };
|
||||
| ^^^^^^^^^^^^ `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}` needs to be a pointer-like type
|
||||
|
|
||||
= help: the trait `PointerLike` is not implemented for `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,14 +1,17 @@
|
||||
error[E0277]: `&T` needs to have the same ABI as a pointer
|
||||
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
||||
|
|
||||
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||
| - this type parameter needs to be `Sized`
|
||||
LL | dyn_debug(t);
|
||||
| ^ `&T` needs to be a pointer-like type
|
||||
|
|
||||
= help: the trait `PointerLike` is not implemented for `&T`
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
= note: required for `&T` to implement `PointerLike`
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||
LL + fn polymorphic<T: Debug>(t: &T) {
|
||||
|
|
||||
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerLike {
|
||||
| +++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -1,14 +1,17 @@
|
||||
error[E0277]: `&T` needs to have the same ABI as a pointer
|
||||
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
||||
|
|
||||
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||
| - this type parameter needs to be `Sized`
|
||||
LL | dyn_debug(t);
|
||||
| ^ `&T` needs to be a pointer-like type
|
||||
|
|
||||
= help: the trait `PointerLike` is not implemented for `&T`
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
= note: required for `&T` to implement `PointerLike`
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - fn polymorphic<T: Debug + ?Sized>(t: &T) {
|
||||
LL + fn polymorphic<T: Debug>(t: &T) {
|
||||
|
|
||||
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerLike {
|
||||
| +++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -1,13 +1,18 @@
|
||||
//@ run-pass
|
||||
//@ check-run-results
|
||||
#![feature(dyn_star)]
|
||||
#![feature(dyn_star, pointer_like_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PointerLike;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
struct Foo(#[allow(dead_code)] usize);
|
||||
|
||||
// FIXME(dyn_star): Make this into a derive.
|
||||
impl PointerLike for Foo {}
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("destructor called");
|
||||
|
@ -3,13 +3,18 @@
|
||||
// This used to ICE, because the compiler confused a pointer-like to dyn* coercion
|
||||
// with a c-like enum to integer cast.
|
||||
|
||||
#![feature(dyn_star)]
|
||||
#![feature(dyn_star, pointer_like_trait)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
use std::marker::PointerLike;
|
||||
|
||||
#[repr(transparent)]
|
||||
enum E {
|
||||
Num(usize),
|
||||
}
|
||||
|
||||
impl PointerLike for E {}
|
||||
|
||||
trait Trait {}
|
||||
impl Trait for E {}
|
||||
|
||||
|
@ -7,7 +7,7 @@ trait Foo {}
|
||||
|
||||
fn make_dyn_star() {
|
||||
let i = 42;
|
||||
let dyn_i: dyn* Foo = i; //~ ERROR trait bound `{integer}: Foo` is not satisfied
|
||||
let dyn_i: dyn* Foo = i; //~ ERROR trait bound `usize: Foo` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0277]: the trait bound `{integer}: Foo` is not satisfied
|
||||
error[E0277]: the trait bound `usize: Foo` is not satisfied
|
||||
--> $DIR/error.rs:10:27
|
||||
|
|
||||
LL | let dyn_i: dyn* Foo = i;
|
||||
| ^ the trait `Foo` is not implemented for `{integer}`
|
||||
| ^ the trait `Foo` is not implemented for `usize`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/error.rs:6:1
|
||||
|
16
tests/ui/dyn-star/float-as-dyn-star.rs
Normal file
16
tests/ui/dyn-star/float-as-dyn-star.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//@ only-x86_64
|
||||
|
||||
#![feature(dyn_star, pointer_like_trait)]
|
||||
//~^ WARN the feature `dyn_star` is incomplete
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PointerLike;
|
||||
|
||||
fn make_dyn_star() -> dyn* Debug + 'static {
|
||||
f32::from_bits(0x1) as f64
|
||||
//~^ ERROR `f64` needs to have the same ABI as a pointer
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", make_dyn_star());
|
||||
}
|
21
tests/ui/dyn-star/float-as-dyn-star.stderr
Normal file
21
tests/ui/dyn-star/float-as-dyn-star.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/float-as-dyn-star.rs:3:12
|
||||
|
|
||||
LL | #![feature(dyn_star, pointer_like_trait)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0277]: `f64` needs to have the same ABI as a pointer
|
||||
--> $DIR/float-as-dyn-star.rs:10:5
|
||||
|
|
||||
LL | f32::from_bits(0x1) as f64
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `f64` needs to be a pointer-like type
|
||||
|
|
||||
= help: the trait `PointerLike` is not implemented for `f64`
|
||||
= help: the trait `PointerLike` is implemented for `usize`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -7,6 +7,14 @@ LL | #![feature(dyn_star, trait_upcasting)]
|
||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0277]: `W` needs to have the same ABI as a pointer
|
||||
--> $DIR/upcast.rs:28:23
|
||||
|
|
||||
LL | let w: dyn* Foo = W(0);
|
||||
| ^^^^ `W` needs to be a pointer-like type
|
||||
|
|
||||
= help: the trait `PointerLike` is not implemented for `W`
|
||||
|
||||
error[E0277]: `dyn* Foo` needs to have the same ABI as a pointer
|
||||
--> $DIR/upcast.rs:30:23
|
||||
|
|
||||
@ -15,6 +23,6 @@ LL | let w: dyn* Bar = w;
|
||||
|
|
||||
= help: the trait `PointerLike` is not implemented for `dyn* Foo`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
Loading…
Reference in New Issue
Block a user