Skip to content

Commit

Permalink
eddyb's changes for DST coercions
Browse files Browse the repository at this point in the history
+ lots of rebasing
  • Loading branch information
nrc committed May 13, 2015
1 parent c2b30b8 commit 843db01
Show file tree
Hide file tree
Showing 40 changed files with 1,013 additions and 508 deletions.
8 changes: 8 additions & 0 deletions src/liballoc/boxed.rs
Expand Up @@ -62,6 +62,11 @@ use core::ops::{Deref, DerefMut};
use core::ptr::{Unique};
use core::raw::{TraitObject};

#[cfg(not(stage0))] // SNAP c64d671
use core::marker::Unsize;
#[cfg(not(stage0))] // SNAP c64d671
use core::ops::CoerceUnsized;

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
Expand Down Expand Up @@ -390,3 +395,6 @@ impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
self.call_box(args)
}
}

#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
4 changes: 2 additions & 2 deletions src/liballoc/rc.rs
Expand Up @@ -173,9 +173,9 @@ use core::intrinsics::assume;
use heap::deallocate;

struct RcBox<T> {
value: T,
strong: Cell<usize>,
weak: Cell<usize>
weak: Cell<usize>,
value: T
}

/// A reference-counted pointer type over an immutable value.
Expand Down
7 changes: 7 additions & 0 deletions src/libcore/intrinsics.rs
Expand Up @@ -193,6 +193,13 @@ extern "rust-intrinsic" {
pub fn min_align_of<T>() -> usize;
pub fn pref_align_of<T>() -> usize;

#[cfg(not(stage0))]
pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
#[cfg(not(stage0))]
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
#[cfg(not(stage0))]
pub fn drop_in_place<T: ?Sized>(_: *mut T);

/// Gets a static string slice containing the name of a type.
pub fn type_name<T: ?Sized>() -> &'static str;

Expand Down
8 changes: 8 additions & 0 deletions src/libcore/marker.rs
Expand Up @@ -53,6 +53,14 @@ pub trait Sized {
// Empty.
}

/// Types that can be "unsized" to a dynamically sized type.
#[unstable(feature = "core")]
#[cfg(not(stage0))] // SNAP c64d671
#[lang="unsize"]
pub trait Unsize<T> {
// Empty.
}

/// Types that can be copied by simply copying bits (i.e. `memcpy`).
///
/// By default, variable bindings have 'move semantics.' In other
Expand Down
34 changes: 34 additions & 0 deletions src/libcore/mem.rs
Expand Up @@ -86,6 +86,22 @@ pub fn size_of<T>() -> usize {
unsafe { intrinsics::size_of::<T>() }
}

/// Returns the size of the type that `val` points to in bytes.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::size_of_val(&5i32));
/// ```
#[cfg(not(stage0))] // SNAP c64d671
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::size_of_val(val) }
}

/// Returns the size of the type that `_val` points to in bytes.
///
/// # Examples
Expand All @@ -95,6 +111,7 @@ pub fn size_of<T>() -> usize {
///
/// assert_eq!(4, mem::size_of_val(&5i32));
/// ```
#[cfg(stage0)] // SNAP c64d671
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn size_of_val<T>(_val: &T) -> usize {
Expand All @@ -118,6 +135,22 @@ pub fn min_align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that `val` points to
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::min_align_of_val(&5i32));
/// ```
#[cfg(not(stage0))] // SNAP c64d671
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
}

/// Returns the ABI-required minimum alignment of the type of the value that `_val` points to
///
/// # Examples
Expand All @@ -127,6 +160,7 @@ pub fn min_align_of<T>() -> usize {
///
/// assert_eq!(4, mem::min_align_of_val(&5i32));
/// ```
#[cfg(stage0)] // SNAP c64d671
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn min_align_of_val<T>(_val: &T) -> usize {
Expand Down
5 changes: 5 additions & 0 deletions src/libcore/nonzero.rs
Expand Up @@ -12,6 +12,8 @@

use marker::Sized;
use ops::Deref;
#[cfg(not(stage0))] // SNAP c64d671
use ops::CoerceUnsized;

/// Unsafe trait to indicate what types are usable with the NonZero struct
pub unsafe trait Zeroable {}
Expand Down Expand Up @@ -54,3 +56,6 @@ impl<T: Zeroable> Deref for NonZero<T> {
inner
}
}

#[cfg(not(stage0))] // SNAP c64d671
impl<T: Zeroable+CoerceUnsized<U>, U: Zeroable> CoerceUnsized<NonZero<U>> for NonZero<T> {}
34 changes: 34 additions & 0 deletions src/libcore/ops.rs
Expand Up @@ -70,6 +70,9 @@
use marker::Sized;
use fmt;

#[cfg(not(stage0))] // SNAP c64d671
use marker::Unsize;

/// The `Drop` trait is used to run some code when a value goes out of scope. This
/// is sometimes called a 'destructor'.
///
Expand Down Expand Up @@ -1207,3 +1210,34 @@ mod impls {
}
}
}

/// Trait that indicates that this is a pointer or a wrapper for one,
/// where unsizing can be performed on the pointee.
#[unstable(feature = "core")]
#[cfg(not(stage0))] // SNAP c64d671
#[lang="coerce_unsized"]
pub trait CoerceUnsized<T> {
// Empty.
}

#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}

#[cfg(not(stage0))] // SNAP c64d671
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}

#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}

#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
3 changes: 3 additions & 0 deletions src/librustc/diagnostics.rs
Expand Up @@ -807,6 +807,9 @@ register_diagnostics! {
E0017,
E0019,
E0022,
E0038,
E0079, // enum variant: expected signed integer constant
E0080, // enum variant: constant evaluation error
E0109,
E0110,
E0134,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/metadata/common.rs
Expand Up @@ -259,3 +259,5 @@ pub const tag_codemap_filemap: usize = 0xa2;
pub const tag_item_super_predicates: usize = 0xa3;

pub const tag_defaulted_trait: usize = 0xa4;

pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
8 changes: 8 additions & 0 deletions src/librustc/metadata/csearch.rs
Expand Up @@ -279,6 +279,14 @@ pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
decoder::get_impl_polarity(&*cdata, def.node)
}

pub fn get_custom_coerce_unsized_kind<'tcx>(tcx: &ty::ctxt<'tcx>,
def: ast::DefId)
-> Option<ty::CustomCoerceUnsized> {
let cstore = &tcx.sess.cstore;
let cdata = cstore.get_crate_data(def.krate);
decoder::get_custom_coerce_unsized_kind(&*cdata, def.node)
}

// Given a def_id for an impl, return the trait it implements,
// if there is one.
pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/metadata/decoder.rs
Expand Up @@ -489,6 +489,16 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
}
}

pub fn get_custom_coerce_unsized_kind<'tcx>(cdata: Cmd,
id: ast::NodeId)
-> Option<ty::CustomCoerceUnsized> {
let item_doc = lookup_item(id, cdata.data());
reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
let mut decoder = reader::Decoder::new(kind_doc);
Decodable::decode(&mut decoder).unwrap()
})
}

pub fn get_impl_trait<'tcx>(cdata: Cmd,
id: ast::NodeId,
tcx: &ty::ctxt<'tcx>)
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/metadata/encoder.rs
Expand Up @@ -1219,6 +1219,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_attributes(rbml_w, &item.attrs);
encode_unsafety(rbml_w, unsafety);
encode_polarity(rbml_w, polarity);

match tcx.custom_coerce_unsized_kinds.borrow().get(&local_def(item.id)) {
Some(&kind) => {
rbml_w.start_tag(tag_impl_coerce_unsized_kind);
kind.encode(rbml_w);
rbml_w.end_tag();
}
None => {}
}

match ty.node {
ast::TyPath(None, ref path) if path.segments.len() == 1 => {
let name = path.segments.last().unwrap().identifier.name;
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/middle/expr_use_visitor.rs
Expand Up @@ -890,10 +890,6 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
}
};

debug!("walk_autoref: expr.id={} cmt_base={}",
expr.id,
cmt_base.repr(self.tcx()));

match *autoref {
ty::AutoPtr(r, m) => {
self.delegate.borrow(expr.id,
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/middle/lang_items.rs
Expand Up @@ -261,11 +261,14 @@ lets_do_this! {

SendTraitLangItem, "send", send_trait;
SizedTraitLangItem, "sized", sized_trait;
UnsizeTraitLangItem, "unsize", unsize_trait;
CopyTraitLangItem, "copy", copy_trait;
SyncTraitLangItem, "sync", sync_trait;

DropTraitLangItem, "drop", drop_trait;

CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait;

AddTraitLangItem, "add", add_trait;
SubTraitLangItem, "sub", sub_trait;
MulTraitLangItem, "mul", mul_trait;
Expand Down
56 changes: 52 additions & 4 deletions src/librustc/middle/traits/error_reporting.rs
Expand Up @@ -15,8 +15,12 @@ use super::{
Obligation,
ObligationCauseCode,
OutputTypeParameterMismatch,
TraitNotObjectSafe,
PredicateObligation,
SelectionError,
ObjectSafetyViolation,
MethodViolationCode,
object_safety_violations,
};

use fmt_macros::{Parser, Piece, Position};
Expand Down Expand Up @@ -252,6 +256,54 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
note_obligation_cause(infcx, obligation);
}
}

TraitNotObjectSafe(did) => {
span_err!(infcx.tcx.sess, obligation.cause.span, E0038,
"cannot convert to a trait object because trait `{}` is not object-safe",
ty::item_path_str(infcx.tcx, did));

for violation in object_safety_violations(infcx.tcx, did) {
match violation {
ObjectSafetyViolation::SizedSelf => {
infcx.tcx.sess.span_note(
obligation.cause.span,
"the trait cannot require that `Self : Sized`");
}

ObjectSafetyViolation::SupertraitSelf => {
infcx.tcx.sess.span_note(
obligation.cause.span,
"the trait cannot use `Self` as a type parameter \
in the supertrait listing");
}

ObjectSafetyViolation::Method(method,
MethodViolationCode::StaticMethod) => {
infcx.tcx.sess.span_note(
obligation.cause.span,
&format!("method `{}` has no receiver",
method.name.user_string(infcx.tcx)));
}

ObjectSafetyViolation::Method(method,
MethodViolationCode::ReferencesSelf) => {
infcx.tcx.sess.span_note(
obligation.cause.span,
&format!("method `{}` references the `Self` type \
in its arguments or return type",
method.name.user_string(infcx.tcx)));
}

ObjectSafetyViolation::Method(method,
MethodViolationCode::Generic) => {
infcx.tcx.sess.span_note(
obligation.cause.span,
&format!("method `{}` has generic type parameters",
method.name.user_string(infcx.tcx)));
}
}
}
}
}
}

Expand Down Expand Up @@ -403,10 +455,6 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
"only the last field of a struct or enum variant \
may have a dynamically sized type")
}
ObligationCauseCode::ObjectSized => {
span_note!(tcx.sess, cause_span,
"only sized types can be made into objects");
}
ObligationCauseCode::SharedStatic => {
span_note!(tcx.sess, cause_span,
"shared static variables must have a type that implements `Sync`");
Expand Down
10 changes: 6 additions & 4 deletions src/librustc/middle/traits/mod.rs
Expand Up @@ -28,6 +28,7 @@ use util::ppaux::Repr;

pub use self::error_reporting::report_fulfillment_errors;
pub use self::error_reporting::report_overflow_error;
pub use self::error_reporting::report_selection_error;
pub use self::error_reporting::suggest_new_overflow_limit;
pub use self::coherence::orphan_check;
pub use self::coherence::overlapping_impls;
Expand All @@ -48,6 +49,7 @@ pub use self::select::{MethodMatchedData}; // intentionally don't export variant
pub use self::util::elaborate_predicates;
pub use self::util::get_vtable_index_of_object_method;
pub use self::util::trait_ref_for_builtin_bound;
pub use self::util::predicate_for_trait_def;
pub use self::util::supertraits;
pub use self::util::Supertraits;
pub use self::util::supertrait_def_ids;
Expand Down Expand Up @@ -121,9 +123,6 @@ pub enum ObligationCauseCode<'tcx> {
// Types of fields (other than the last) in a struct must be sized.
FieldSized,

// Only Sized types can be made into objects
ObjectSized,

// static items must have `Sync` type
SharedStatic,

Expand Down Expand Up @@ -159,6 +158,7 @@ pub enum SelectionError<'tcx> {
OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
ty::PolyTraitRef<'tcx>,
ty::type_err<'tcx>),
TraitNotObjectSafe(ast::DefId),
}

pub struct FulfillmentError<'tcx> {
Expand Down Expand Up @@ -536,7 +536,9 @@ impl<'tcx, N> Vtable<'tcx, N> {
}
}

pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M {
pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where
F: FnMut(&N) -> M,
{
match *self {
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)),
Expand Down

0 comments on commit 843db01

Please sign in to comment.