Skip to content

Commit 381cb11

Browse files
committed
eddyb's changes for DST coercions
+ lots of rebasing
1 parent 5910dc0 commit 381cb11

40 files changed

+1010
-507
lines changed

src/liballoc/boxed.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ use core::ops::{Deref, DerefMut};
5858
use core::ptr::{Unique};
5959
use core::raw::{TraitObject};
6060

61+
#[cfg(not(stage0))] // SNAP c64d671
62+
use core::marker::Unsize;
63+
#[cfg(not(stage0))] // SNAP c64d671
64+
use core::ops::CoerceUnsized;
65+
6166
/// A value that represents the heap. This is the default place that the `box`
6267
/// keyword allocates into when no place is supplied.
6368
///
@@ -381,3 +386,6 @@ impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
381386
self.call_box(args)
382387
}
383388
}
389+
390+
#[cfg(not(stage0))] // SNAP c64d671
391+
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}

src/liballoc/rc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ use core::intrinsics::assume;
173173
use heap::deallocate;
174174

175175
struct RcBox<T> {
176-
value: T,
177176
strong: Cell<usize>,
178-
weak: Cell<usize>
177+
weak: Cell<usize>,
178+
value: T
179179
}
180180

181181
/// A reference-counted pointer type over an immutable value.

src/libcore/intrinsics.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ extern "rust-intrinsic" {
178178
pub fn min_align_of<T>() -> usize;
179179
pub fn pref_align_of<T>() -> usize;
180180

181+
#[cfg(not(stage0))]
182+
pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
183+
#[cfg(not(stage0))]
184+
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
185+
#[cfg(not(stage0))]
186+
pub fn drop_in_place<T: ?Sized>(_: *mut T);
187+
181188
/// Gets a static string slice containing the name of a type.
182189
pub fn type_name<T: ?Sized>() -> &'static str;
183190

src/libcore/marker.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ pub trait Sized : MarkerTrait {
5656
// Empty.
5757
}
5858

59+
/// Types that can be "unsized" to a dynamically sized type.
60+
#[unstable(feature = "core")]
61+
#[cfg(not(stage0))] // SNAP c64d671
62+
#[lang="unsize"]
63+
pub trait Unsize<T> {
64+
// Empty.
65+
}
66+
5967
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
6068
///
6169
/// By default, variable bindings have 'move semantics.' In other

src/libcore/mem.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ pub fn size_of<T>() -> usize {
4747
unsafe { intrinsics::size_of::<T>() }
4848
}
4949

50+
/// Returns the size of the type that `val` points to in bytes.
51+
///
52+
/// # Examples
53+
///
54+
/// ```
55+
/// use std::mem;
56+
///
57+
/// assert_eq!(4, mem::size_of_val(&5i32));
58+
/// ```
59+
#[cfg(not(stage0))] // SNAP c64d671
60+
#[inline]
61+
#[stable(feature = "rust1", since = "1.0.0")]
62+
pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
63+
unsafe { intrinsics::size_of_val(val) }
64+
}
65+
5066
/// Returns the size of the type that `_val` points to in bytes.
5167
///
5268
/// # Examples
@@ -56,6 +72,7 @@ pub fn size_of<T>() -> usize {
5672
///
5773
/// assert_eq!(4, mem::size_of_val(&5i32));
5874
/// ```
75+
#[cfg(stage0)] // SNAP c64d671
5976
#[inline]
6077
#[stable(feature = "rust1", since = "1.0.0")]
6178
pub fn size_of_val<T>(_val: &T) -> usize {
@@ -79,6 +96,22 @@ pub fn min_align_of<T>() -> usize {
7996
unsafe { intrinsics::min_align_of::<T>() }
8097
}
8198

99+
/// Returns the ABI-required minimum alignment of the type of the value that `val` points to
100+
///
101+
/// # Examples
102+
///
103+
/// ```
104+
/// use std::mem;
105+
///
106+
/// assert_eq!(4, mem::min_align_of_val(&5i32));
107+
/// ```
108+
#[cfg(not(stage0))] // SNAP c64d671
109+
#[inline]
110+
#[stable(feature = "rust1", since = "1.0.0")]
111+
pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
112+
unsafe { intrinsics::min_align_of_val(val) }
113+
}
114+
82115
/// Returns the ABI-required minimum alignment of the type of the value that `_val` points to
83116
///
84117
/// # Examples
@@ -88,6 +121,7 @@ pub fn min_align_of<T>() -> usize {
88121
///
89122
/// assert_eq!(4, mem::min_align_of_val(&5i32));
90123
/// ```
124+
#[cfg(stage0)] // SNAP c64d671
91125
#[inline]
92126
#[stable(feature = "rust1", since = "1.0.0")]
93127
pub fn min_align_of_val<T>(_val: &T) -> usize {

src/libcore/nonzero.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
1313
use marker::{Sized, MarkerTrait};
1414
use ops::Deref;
15+
#[cfg(not(stage0))] // SNAP c64d671
16+
use ops::CoerceUnsized;
1517

1618
/// Unsafe trait to indicate what types are usable with the NonZero struct
1719
#[allow(deprecated)]
@@ -55,3 +57,6 @@ impl<T: Zeroable> Deref for NonZero<T> {
5557
inner
5658
}
5759
}
60+
61+
#[cfg(not(stage0))] // SNAP c64d671
62+
impl<T: Zeroable+CoerceUnsized<U>, U: Zeroable> CoerceUnsized<NonZero<U>> for NonZero<T> {}

src/libcore/ops.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@
7070
use marker::Sized;
7171
use fmt;
7272

73+
#[cfg(not(stage0))] // SNAP c64d671
74+
use marker::Unsize;
75+
7376
/// The `Drop` trait is used to run some code when a value goes out of scope. This
7477
/// is sometimes called a 'destructor'.
7578
///
@@ -1210,3 +1213,34 @@ mod impls {
12101213
}
12111214
}
12121215
}
1216+
1217+
/// Trait that indicates that this is a pointer or a wrapper for one,
1218+
/// where unsizing can be performed on the pointee.
1219+
#[unstable(feature = "core")]
1220+
#[cfg(not(stage0))] // SNAP c64d671
1221+
#[lang="coerce_unsized"]
1222+
pub trait CoerceUnsized<T> {
1223+
// Empty.
1224+
}
1225+
1226+
#[cfg(not(stage0))] // SNAP c64d671
1227+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
1228+
#[cfg(not(stage0))] // SNAP c64d671
1229+
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
1230+
#[cfg(not(stage0))] // SNAP c64d671
1231+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
1232+
#[cfg(not(stage0))] // SNAP c64d671
1233+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
1234+
1235+
#[cfg(not(stage0))] // SNAP c64d671
1236+
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
1237+
#[cfg(not(stage0))] // SNAP c64d671
1238+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
1239+
1240+
#[cfg(not(stage0))] // SNAP c64d671
1241+
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
1242+
#[cfg(not(stage0))] // SNAP c64d671
1243+
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
1244+
1245+
#[cfg(not(stage0))] // SNAP c64d671
1246+
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}

src/librustc/diagnostics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ register_diagnostics! {
416416
E0018,
417417
E0019,
418418
E0022,
419+
E0038,
419420
E0079, // enum variant: expected signed integer constant
420421
E0080, // enum variant: constant evaluation error
421422
E0109,

src/librustc/metadata/common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,5 @@ pub const tag_codemap_filemap: usize = 0xa2;
256256
pub const tag_item_super_predicates: usize = 0xa3;
257257

258258
pub const tag_defaulted_trait: usize = 0xa4;
259+
260+
pub const tag_impl_coerce_unsized_kind: usize = 0xa5;

src/librustc/metadata/csearch.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,14 @@ pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
272272
decoder::get_impl_polarity(&*cdata, def.node)
273273
}
274274

275+
pub fn get_custom_coerce_unsized_kind<'tcx>(tcx: &ty::ctxt<'tcx>,
276+
def: ast::DefId)
277+
-> Option<ty::CustomCoerceUnsized> {
278+
let cstore = &tcx.sess.cstore;
279+
let cdata = cstore.get_crate_data(def.krate);
280+
decoder::get_custom_coerce_unsized_kind(&*cdata, def.node)
281+
}
282+
275283
// Given a def_id for an impl, return the trait it implements,
276284
// if there is one.
277285
pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,

src/librustc/metadata/decoder.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,16 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
470470
}
471471
}
472472

473+
pub fn get_custom_coerce_unsized_kind<'tcx>(cdata: Cmd,
474+
id: ast::NodeId)
475+
-> Option<ty::CustomCoerceUnsized> {
476+
let item_doc = lookup_item(id, cdata.data());
477+
reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
478+
let mut decoder = reader::Decoder::new(kind_doc);
479+
Decodable::decode(&mut decoder).unwrap()
480+
})
481+
}
482+
473483
pub fn get_impl_trait<'tcx>(cdata: Cmd,
474484
id: ast::NodeId,
475485
tcx: &ty::ctxt<'tcx>)

src/librustc/metadata/encoder.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
11851185
encode_attributes(rbml_w, &item.attrs);
11861186
encode_unsafety(rbml_w, unsafety);
11871187
encode_polarity(rbml_w, polarity);
1188+
1189+
match tcx.custom_coerce_unsized_kinds.borrow().get(&local_def(item.id)) {
1190+
Some(&kind) => {
1191+
rbml_w.start_tag(tag_impl_coerce_unsized_kind);
1192+
kind.encode(rbml_w);
1193+
rbml_w.end_tag();
1194+
}
1195+
None => {}
1196+
}
1197+
11881198
match ty.node {
11891199
ast::TyPath(None, ref path) if path.segments.len() == 1 => {
11901200
let name = path.segments.last().unwrap().identifier.name;

src/librustc/middle/expr_use_visitor.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -890,10 +890,6 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
890890
}
891891
};
892892

893-
debug!("walk_autoref: expr.id={} cmt_base={}",
894-
expr.id,
895-
cmt_base.repr(self.tcx()));
896-
897893
match *autoref {
898894
ty::AutoPtr(r, m) => {
899895
self.delegate.borrow(expr.id,

src/librustc/middle/lang_items.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,11 +259,14 @@ lets_do_this! {
259259

260260
SendTraitLangItem, "send", send_trait;
261261
SizedTraitLangItem, "sized", sized_trait;
262+
UnsizeTraitLangItem, "unsize", unsize_trait;
262263
CopyTraitLangItem, "copy", copy_trait;
263264
SyncTraitLangItem, "sync", sync_trait;
264265

265266
DropTraitLangItem, "drop", drop_trait;
266267

268+
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait;
269+
267270
AddTraitLangItem, "add", add_trait;
268271
SubTraitLangItem, "sub", sub_trait;
269272
MulTraitLangItem, "mul", mul_trait;

src/librustc/middle/traits/error_reporting.rs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ use super::{
1515
Obligation,
1616
ObligationCauseCode,
1717
OutputTypeParameterMismatch,
18+
TraitNotObjectSafe,
1819
PredicateObligation,
1920
SelectionError,
21+
ObjectSafetyViolation,
22+
MethodViolationCode,
23+
object_safety_violations,
2024
};
2125

2226
use fmt_macros::{Parser, Piece, Position};
@@ -246,6 +250,54 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
246250
note_obligation_cause(infcx, obligation);
247251
}
248252
}
253+
254+
TraitNotObjectSafe(did) => {
255+
span_err!(infcx.tcx.sess, obligation.cause.span, E0038,
256+
"cannot convert to a trait object because trait `{}` is not object-safe",
257+
ty::item_path_str(infcx.tcx, did));
258+
259+
for violation in object_safety_violations(infcx.tcx, did) {
260+
match violation {
261+
ObjectSafetyViolation::SizedSelf => {
262+
infcx.tcx.sess.span_note(
263+
obligation.cause.span,
264+
"the trait cannot require that `Self : Sized`");
265+
}
266+
267+
ObjectSafetyViolation::SupertraitSelf => {
268+
infcx.tcx.sess.span_note(
269+
obligation.cause.span,
270+
"the trait cannot use `Self` as a type parameter \
271+
in the supertrait listing");
272+
}
273+
274+
ObjectSafetyViolation::Method(method,
275+
MethodViolationCode::StaticMethod) => {
276+
infcx.tcx.sess.span_note(
277+
obligation.cause.span,
278+
&format!("method `{}` has no receiver",
279+
method.name.user_string(infcx.tcx)));
280+
}
281+
282+
ObjectSafetyViolation::Method(method,
283+
MethodViolationCode::ReferencesSelf) => {
284+
infcx.tcx.sess.span_note(
285+
obligation.cause.span,
286+
&format!("method `{}` references the `Self` type \
287+
in its arguments or return type",
288+
method.name.user_string(infcx.tcx)));
289+
}
290+
291+
ObjectSafetyViolation::Method(method,
292+
MethodViolationCode::Generic) => {
293+
infcx.tcx.sess.span_note(
294+
obligation.cause.span,
295+
&format!("method `{}` has generic type parameters",
296+
method.name.user_string(infcx.tcx)));
297+
}
298+
}
299+
}
300+
}
249301
}
250302
}
251303

@@ -397,10 +449,6 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
397449
"only the last field of a struct or enum variant \
398450
may have a dynamically sized type")
399451
}
400-
ObligationCauseCode::ObjectSized => {
401-
span_note!(tcx.sess, cause_span,
402-
"only sized types can be made into objects");
403-
}
404452
ObligationCauseCode::SharedStatic => {
405453
span_note!(tcx.sess, cause_span,
406454
"shared static variables must have a type that implements `Sync`");

src/librustc/middle/traits/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use util::ppaux::Repr;
2727

2828
pub use self::error_reporting::report_fulfillment_errors;
2929
pub use self::error_reporting::report_overflow_error;
30+
pub use self::error_reporting::report_selection_error;
3031
pub use self::error_reporting::suggest_new_overflow_limit;
3132
pub use self::coherence::orphan_check;
3233
pub use self::coherence::overlapping_impls;
@@ -47,6 +48,7 @@ pub use self::select::{MethodMatchedData}; // intentionally don't export variant
4748
pub use self::util::elaborate_predicates;
4849
pub use self::util::get_vtable_index_of_object_method;
4950
pub use self::util::trait_ref_for_builtin_bound;
51+
pub use self::util::predicate_for_trait_def;
5052
pub use self::util::supertraits;
5153
pub use self::util::Supertraits;
5254
pub use self::util::supertrait_def_ids;
@@ -120,9 +122,6 @@ pub enum ObligationCauseCode<'tcx> {
120122
// Types of fields (other than the last) in a struct must be sized.
121123
FieldSized,
122124

123-
// Only Sized types can be made into objects
124-
ObjectSized,
125-
126125
// static items must have `Sync` type
127126
SharedStatic,
128127

@@ -158,6 +157,7 @@ pub enum SelectionError<'tcx> {
158157
OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
159158
ty::PolyTraitRef<'tcx>,
160159
ty::type_err<'tcx>),
160+
TraitNotObjectSafe(ast::DefId),
161161
}
162162

163163
pub struct FulfillmentError<'tcx> {
@@ -534,7 +534,9 @@ impl<'tcx, N> Vtable<'tcx, N> {
534534
}
535535
}
536536

537-
pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M {
537+
pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where
538+
F: FnMut(&N) -> M,
539+
{
538540
match *self {
539541
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
540542
VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)),

0 commit comments

Comments
 (0)