Skip to content

Take 2: Implement object-safety and dynamic dispatch for arbitrary_self_types #54383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Nov 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d14af13
Make all object-safety methods require a global TyCtxt
mikeyhew Jul 2, 2018
a920036
move some code around to avoid query cycles
mikeyhew Sep 20, 2018
be80a79
Add CoerceSized trait and lang item
mikeyhew Sep 20, 2018
d5c2c4a
Implement the object-safety checks for arbitrary_self_types: part 1
mikeyhew Sep 20, 2018
9f59da2
Implement object-safety for arbitrary_self_types: part 2
mikeyhew Sep 20, 2018
192900e
Add CoerceSized impls throughout libstd
mikeyhew Sep 20, 2018
a0f23f8
update tests that have changed output
mikeyhew Sep 20, 2018
82f1f9a
Add new tests and update existing for object-safe custom receivers
mikeyhew Sep 20, 2018
c29641e
fix docs on trait
mikeyhew Sep 21, 2018
f12c250
Replace CoerceSized trait with DispatchFromDyn
mikeyhew Oct 4, 2018
48d7f8d
update DispatchFromDyn doctest
mikeyhew Oct 5, 2018
3c56d8d
fix error-index test
mikeyhew Oct 5, 2018
74ef46c
Replace UncoeribleReceiver error message with UndispatchableReceiver
mikeyhew Oct 9, 2018
6f2a161
Add layout sanity checks in object safety
mikeyhew Oct 9, 2018
b5b25f8
Put backticks around field names, types and paths in error messages
mikeyhew Oct 9, 2018
eb997d7
add `U: Trait` to the param env during DispatchFromDyn check
mikeyhew Oct 12, 2018
3db2203
Remove this check for object-safety during selection of trait object …
mikeyhew Oct 17, 2018
a468da9
Add a check for reprs that could change the ABI
mikeyhew Oct 26, 2018
192e7c4
Add comments explaining how codegen works for `dyn Trait` methods
mikeyhew Nov 1, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ use core::iter::FusedIterator;
use core::marker::{Unpin, Unsize};
use core::mem;
use core::pin::Pin;
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
use core::ops::{CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Generator, GeneratorState};
use core::ptr::{self, NonNull, Unique};
use core::task::{LocalWaker, Poll};

Expand Down Expand Up @@ -696,6 +696,9 @@ impl<'a, A, R> FnOnce<A> for Box<dyn FnBox<A, Output = R> + Send + 'a> {
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}

#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}

#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl<T: Clone> Clone for Box<[T]> {
fn clone(&self) -> Self {
Expand Down
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
#![feature(box_syntax)]
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
#![feature(dispatch_from_dyn)]
#![feature(core_intrinsics)]
#![feature(custom_attribute)]
#![feature(dropck_eyepatch)]
Expand Down
8 changes: 7 additions & 1 deletion src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ use core::marker;
use core::marker::{Unpin, Unsize, PhantomData};
use core::mem::{self, align_of_val, forget, size_of_val};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ops::{CoerceUnsized, DispatchFromDyn};
use core::pin::Pin;
use core::ptr::{self, NonNull};
use core::convert::From;
Expand Down Expand Up @@ -297,6 +297,9 @@ impl<T: ?Sized> !marker::Sync for Rc<T> {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}

#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}

impl<T> Rc<T> {
/// Constructs a new `Rc<T>`.
///
Expand Down Expand Up @@ -1176,6 +1179,9 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}

#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}

impl<T> Weak<T> {
/// Constructs a new `Weak<T>`, without allocating any memory.
/// Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`].
Expand Down
7 changes: 6 additions & 1 deletion src/liballoc/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use core::cmp::Ordering;
use core::intrinsics::abort;
use core::mem::{self, align_of_val, size_of_val};
use core::ops::Deref;
use core::ops::CoerceUnsized;
use core::ops::{CoerceUnsized, DispatchFromDyn};
use core::pin::Pin;
use core::ptr::{self, NonNull};
use core::marker::{Unpin, Unsize, PhantomData};
Expand Down Expand Up @@ -214,6 +214,9 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}

#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}

/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
/// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
Expand Down Expand Up @@ -254,6 +257,8 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}

#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}

#[stable(feature = "arc_weak", since = "1.4.0")]
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
Expand Down
4 changes: 3 additions & 1 deletion src/libcore/nonzero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

//! Exposes the NonZero lang item which provides optimization hints.

use ops::CoerceUnsized;
use ops::{CoerceUnsized, DispatchFromDyn};

/// A wrapper type for raw pointers and integers that will never be
/// NULL or 0 that might allow certain optimizations.
Expand All @@ -20,3 +20,5 @@ use ops::CoerceUnsized;
pub(crate) struct NonZero<T>(pub(crate) T);

impl<T: CoerceUnsized<U>, U> CoerceUnsized<NonZero<U>> for NonZero<T> {}

impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<NonZero<U>> for NonZero<T> {}
3 changes: 3 additions & 0 deletions src/libcore/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,6 @@ pub use self::generator::{Generator, GeneratorState};

#[unstable(feature = "coerce_unsized", issue = "27732")]
pub use self::unsize::CoerceUnsized;

#[unstable(feature = "dispatch_from_dyn", issue = "0")]
pub use self::unsize::DispatchFromDyn;
36 changes: 35 additions & 1 deletion src/libcore/ops/unsize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use marker::Unsize;
/// [nomicon-coerce]: ../../nomicon/coercions.html
#[unstable(feature = "coerce_unsized", issue = "27732")]
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {
pub trait CoerceUnsized<T: ?Sized> {
// Empty.
}

Expand Down Expand Up @@ -77,3 +77,37 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
// *const T -> *const U
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}


/// This is used for object safety, to check that a method's receiver type can be dispatched on.
///
/// example impl:
///
/// ```
/// # #![feature(dispatch_from_dyn, unsize)]
/// # use std::{ops::DispatchFromDyn, marker::Unsize};
/// # struct Rc<T: ?Sized>(::std::rc::Rc<T>);
/// impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T>
/// where
/// T: Unsize<U>,
/// {}
/// ```
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
#[cfg_attr(not(stage0), lang = "dispatch_from_dyn")]
pub trait DispatchFromDyn<T> {
// Empty.
}

// &T -> &U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
// &mut T -> &mut U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
// *const T -> *const U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
// *mut T -> *mut U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}

8 changes: 7 additions & 1 deletion src/libcore/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@

use fmt;
use marker::Sized;
use ops::{Deref, DerefMut, CoerceUnsized};
use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn};

#[doc(inline)]
pub use marker::Unpin;
Expand Down Expand Up @@ -324,5 +324,11 @@ where
P: CoerceUnsized<U>,
{}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, P, U> DispatchFromDyn<Pin<U>> for Pin<P>
where
P: DispatchFromDyn<U>,
{}

#[unstable(feature = "pin", issue = "49150")]
impl<P> Unpin for Pin<P> {}
8 changes: 7 additions & 1 deletion src/libcore/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@

use convert::From;
use intrinsics;
use ops::CoerceUnsized;
use ops::{CoerceUnsized, DispatchFromDyn};
use fmt;
use hash;
use marker::{PhantomData, Unsize};
Expand Down Expand Up @@ -2795,6 +2795,9 @@ impl<T: ?Sized> Copy for Unique<T> { }
#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }

#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> fmt::Pointer for Unique<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down Expand Up @@ -2951,6 +2954,9 @@ impl<T: ?Sized> Copy for NonNull<T> { }
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }

#[unstable(feature = "dispatch_from_dyn", issue = "0")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }

#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: ?Sized> fmt::Debug for NonNull<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ language_item_table! {
DropTraitLangItem, "drop", drop_trait, Target::Trait;

CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait;
DispatchFromDynTraitLangItem,"dispatch_from_dyn", dispatch_from_dyn_trait, Target::Trait;

AddTraitLangItem, "add", add_trait, Target::Trait;
SubTraitLangItem, "sub", sub_trait, Target::Trait;
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

ty::Predicate::ObjectSafe(trait_def_id) => {
let violations = self.tcx.object_safety_violations(trait_def_id);
let violations = self.tcx.global_tcx()
.object_safety_violations(trait_def_id);
self.tcx.report_object_safety_error(span,
trait_def_id,
violations)
Expand Down Expand Up @@ -875,7 +876,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

TraitNotObjectSafe(did) => {
let violations = self.tcx.object_safety_violations(did);
let violations = self.tcx.global_tcx().object_safety_violations(did);
self.tcx.report_object_safety_error(span, did, violations)
}

Expand Down
Loading