mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +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> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let lang_items = tcx.lang_items();
|
let lang_items = tcx.lang_items();
|
||||||
let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
|
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);
|
checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
|
||||||
res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy));
|
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.const_param_ty_trait(), |checker| {
|
||||||
visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
|
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)
|
visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
|
||||||
}));
|
})?;
|
||||||
|
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
|
||||||
res = res.and(
|
|
||||||
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized),
|
|
||||||
);
|
|
||||||
res.and(
|
|
||||||
checker
|
checker
|
||||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn),
|
.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> {
|
struct Checker<'tcx> {
|
||||||
@ -663,3 +660,63 @@ fn infringing_fields_error<'tcx>(
|
|||||||
|
|
||||||
err.emit()
|
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::fmt;
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
use core::marker::PointerLike;
|
||||||
use core::marker::{Tuple, Unsize};
|
use core::marker::{Tuple, Unsize};
|
||||||
use core::mem::{self, SizedTypeProperties};
|
use core::mem::{self, SizedTypeProperties};
|
||||||
use core::ops::{
|
use core::ops::{
|
||||||
@ -2131,3 +2133,7 @@ impl<E: Error> Error for Box<E> {
|
|||||||
Error::provide(&**self, request);
|
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(panic_internals)]
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
#![feature(pin_coerce_unsized_trait)]
|
#![feature(pin_coerce_unsized_trait)]
|
||||||
|
#![feature(pointer_like_trait)]
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(ptr_sub_ptr)]
|
#![feature(ptr_sub_ptr)]
|
||||||
|
@ -981,6 +981,18 @@ pub trait Tuple {}
|
|||||||
)]
|
)]
|
||||||
pub trait PointerLike {}
|
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.
|
/// 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
|
/// 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
|
error[E0277]: `&T` needs to have the same ABI as a pointer
|
||||||
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
--> $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);
|
LL | dyn_debug(t);
|
||||||
| ^ `&T` needs to be a pointer-like type
|
| ^ `&T` needs to be a pointer-like type
|
||||||
|
|
|
|
||||||
= help: the trait `PointerLike` is not implemented for `&T`
|
= note: required for `&T` to implement `PointerLike`
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
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
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
error[E0277]: `&T` needs to have the same ABI as a pointer
|
error[E0277]: `&T` needs to have the same ABI as a pointer
|
||||||
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
--> $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);
|
LL | dyn_debug(t);
|
||||||
| ^ `&T` needs to be a pointer-like type
|
| ^ `&T` needs to be a pointer-like type
|
||||||
|
|
|
|
||||||
= help: the trait `PointerLike` is not implemented for `&T`
|
= note: required for `&T` to implement `PointerLike`
|
||||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
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
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
//@ run-pass
|
//@ run-pass
|
||||||
//@ check-run-results
|
//@ check-run-results
|
||||||
#![feature(dyn_star)]
|
#![feature(dyn_star, pointer_like_trait)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::marker::PointerLike;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
struct Foo(#[allow(dead_code)] usize);
|
struct Foo(#[allow(dead_code)] usize);
|
||||||
|
|
||||||
|
// FIXME(dyn_star): Make this into a derive.
|
||||||
|
impl PointerLike for Foo {}
|
||||||
|
|
||||||
impl Drop for Foo {
|
impl Drop for Foo {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
println!("destructor called");
|
println!("destructor called");
|
||||||
|
@ -3,13 +3,18 @@
|
|||||||
// This used to ICE, because the compiler confused a pointer-like to dyn* coercion
|
// This used to ICE, because the compiler confused a pointer-like to dyn* coercion
|
||||||
// with a c-like enum to integer cast.
|
// with a c-like enum to integer cast.
|
||||||
|
|
||||||
#![feature(dyn_star)]
|
#![feature(dyn_star, pointer_like_trait)]
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
|
use std::marker::PointerLike;
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
enum E {
|
enum E {
|
||||||
Num(usize),
|
Num(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PointerLike for E {}
|
||||||
|
|
||||||
trait Trait {}
|
trait Trait {}
|
||||||
impl Trait for E {}
|
impl Trait for E {}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ trait Foo {}
|
|||||||
|
|
||||||
fn make_dyn_star() {
|
fn make_dyn_star() {
|
||||||
let i = 42;
|
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() {}
|
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
|
--> $DIR/error.rs:10:27
|
||||||
|
|
|
|
||||||
LL | let dyn_i: dyn* Foo = i;
|
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
|
help: this trait has no implementations, consider adding one
|
||||||
--> $DIR/error.rs:6:1
|
--> $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: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= 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
|
error[E0277]: `dyn* Foo` needs to have the same ABI as a pointer
|
||||||
--> $DIR/upcast.rs:30:23
|
--> $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`
|
= 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`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
Loading…
Reference in New Issue
Block a user