Skip to content
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

Implement object-safety for arbitrary_self_types #50173

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0f0b7cb
Make all object-safety methods require a global TyCtxt
mikeyhew Jul 2, 2018
6e05b92
Try to do the CoerceUnsized check for object safety
mikeyhew Jul 3, 2018
d3af466
reduce line length to please tidy
mikeyhew Jul 13, 2018
09202f3
do the coerce_unsized check last
mikeyhew Jul 13, 2018
0f76082
only check for object-safety if we have an inference variable
mikeyhew Jul 13, 2018
76d3e73
remove some `use` declarations that got added in during rebase
mikeyhew Jul 13, 2018
ebe1199
Add some log messages to aid in debugging
mikeyhew Jul 13, 2018
04cbc1d
re-bind receiver_ty to avoid escaping regions errors
mikeyhew Jul 13, 2018
831e821
It's the receiver type we're checking, not Self
mikeyhew Jul 13, 2018
e5ca14c
allow `self: Self` as a special case for backward-compat
mikeyhew Jul 15, 2018
1509275
keep receiver_ty behind a Binder always
mikeyhew Jul 15, 2018
9cbce68
call liberate_late_bound_regions on receiver_ty
mikeyhew Jul 17, 2018
e3b3167
fix bug when trait arguments appear in `receiver_ty`
mikeyhew Jul 17, 2018
478763b
update object-safety ui test for new object-safety rules
mikeyhew Jul 17, 2018
b31b0f9
create receiver_substs using the method's DefId
mikeyhew Jul 17, 2018
3e8c5bc
update some compile-fail tests
mikeyhew Jul 17, 2018
a63a201
Add the CoerceSized trait
mikeyhew Aug 27, 2018
2598c1f
switch from using CoerceUnsized to CoerceSized for the object-safety …
mikeyhew Aug 28, 2018
c236af3
update comments and fix bug in object_safety.rs
mikeyhew Aug 30, 2018
ffcadd4
update code comments in object-safety.rs
mikeyhew Sep 2, 2018
f85e838
update doc comments and fix tidy lints
mikeyhew Sep 2, 2018
85b25a6
update object_safety module-level documentation
mikeyhew Sep 2, 2018
39e13ae
use [X => Y] instead of [X -> Y] for substitution notation
mikeyhew Sep 2, 2018
9bfb39d
address nit about `{` being on the wrong line
mikeyhew Sep 2, 2018
6b14a12
add ICE message explaining that custom receivers dynamic dispatch is …
mikeyhew Sep 3, 2018
2739801
Finish updating ui tests
mikeyhew Sep 4, 2018
e972b2b
Move CoerceSized from marker to ops
mikeyhew Sep 4, 2018
3c6fcde
Add a test with pointers and wrappers
mikeyhew Sep 4, 2018
01d0a2e
fix issue number for coerce_sized feature
mikeyhew Sep 4, 2018
ad8f4c0
Add a positive test using stdlib pointers
mikeyhew Sep 5, 2018
ac7677f
Undo submodule changes in a63a201ba5f543ddd858bb65881d7e696fde6707
mikeyhew Sep 5, 2018
c5a8553
remove stray newline
mikeyhew Sep 6, 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 @@ -66,7 +66,7 @@ use core::iter::FusedIterator;
use core::marker::{Unpin, Unsize};
use core::mem;
use core::pin::PinMut;
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
use core::ops::{CoerceUnsized, CoerceSized, Deref, DerefMut, Generator, GeneratorState};
use core::ptr::{self, NonNull, Unique};
use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError};

Expand Down Expand Up @@ -670,6 +670,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 = "coerce_sized", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Box<T>> for Box<U> {}

#[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 @@ -88,6 +88,7 @@
#![feature(box_syntax)]
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
#![feature(coerce_sized)]
#![cfg_attr(stage0, feature(const_fn))]
#![cfg_attr(not(stage0), feature(min_const_fn))]
#![feature(core_intrinsics)]
Expand Down
7 changes: 6 additions & 1 deletion src/liballoc/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ use core::convert::From;
use core::fmt;
use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj};
use core::marker::Unsize;
use core::ops::{CoerceUnsized, Deref, DerefMut};
use core::ops::{CoerceUnsized, CoerceSized, Deref, DerefMut};
use core::task::{Context, Poll};

use boxed::Box;
Expand Down Expand Up @@ -256,6 +256,11 @@ impl<T: ?Sized> fmt::Pointer for PinBox<T> {
#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}

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



#[unstable(feature = "pin", issue = "49150")]
impl<T: ?Sized> Unpin for PinBox<T> {}

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::{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, CoerceSized};
use core::ptr::{self, NonNull};
use core::convert::From;
use core::usize;
Expand Down Expand Up @@ -295,6 +295,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 = "coerce_sized", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Rc<T>> for Rc<U> {}

impl<T> Rc<T> {
/// Constructs a new `Rc<T>`.
///
Expand Down Expand Up @@ -1171,6 +1174,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 = "coerce_sized", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Weak<T>> for Weak<U> {}

impl<T> Weak<T> {
/// Constructs a new `Weak<T>`, without allocating any memory.
/// Calling [`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, CoerceSized};
use core::ptr::{self, NonNull};
use core::marker::{Unsize, PhantomData};
use core::hash::{Hash, Hasher};
Expand Down Expand Up @@ -212,6 +212,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 = "coerce_sized", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Arc<T>> for Arc<U> {}

/// `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 @@ -252,6 +255,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 = "coerce_sized", issue = "0")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<Weak<T>> for Weak<U> {}

#[stable(feature = "arc_weak", since = "1.4.0")]
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
Expand Down
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 = "coerce_sized", issue = "0")]
pub use self::unsize::CoerceSized;
33 changes: 32 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,34 @@ 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 {}


/// Pointers to unsized types that can be coerced to a pointer to a sized type,
/// as long as pointee is actually a value of that sized type. This is used for
/// object safety, to check that a method's receiver type can be coerced from the version
/// where `Self = dyn Trait` to the version where `Self = T`, the erased, sized type
/// of the underlying object.
///
/// CoerceSized is implemented for:
/// - &[T] is CoerceSized<&[T; N]> for any N
/// - &Trait is CoerceSized<&T> for any T: Trait
/// - and similarly for &mut T, *const T, *mut T, Box<T>, Rc<T>, Arc<T>
#[unstable(feature = "coerce_sized", issue = "0")]
#[cfg_attr(not(stage0), lang = "coerce_sized")]
pub trait CoerceSized<T> where T: CoerceUnsized<Self> {
// Empty.
}

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

5 changes: 4 additions & 1 deletion src/libcore/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use fmt;
use future::{Future, UnsafeFutureObj};
use marker::{Sized, Unpin, Unsize};
use task::{Context, Poll};
use ops::{Deref, DerefMut, CoerceUnsized};
use ops::{Deref, DerefMut, CoerceUnsized, CoerceSized};

/// A pinned reference.
///
Expand Down Expand Up @@ -141,6 +141,9 @@ impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> {
#[unstable(feature = "pin", issue = "49150")]
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinMut<'a, U>> for PinMut<'a, T> {}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceSized<PinMut<'a, T>> for PinMut<'a, U> {}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {}

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 @@ -252,6 +252,7 @@ language_item_table! {
DropTraitLangItem, "drop", drop_trait;

CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait;
CoerceSizedTraitLangItem, "coerce_sized", coerce_sized_trait;

AddTraitLangItem, "add", add_trait;
SubTraitLangItem, "sub", sub_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 @@ -708,7 +708,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 @@ -835,7 +836,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