Skip to content

Commit 843db01

Browse files
committed
eddyb's changes for DST coercions
+ lots of rebasing
1 parent c2b30b8 commit 843db01

40 files changed

+1013
-508
lines changed

src/liballoc/boxed.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ use core::ops::{Deref, DerefMut};
6262
use core::ptr::{Unique};
6363
use core::raw::{TraitObject};
6464

65+
#[cfg(not(stage0))] // SNAP c64d671
66+
use core::marker::Unsize;
67+
#[cfg(not(stage0))] // SNAP c64d671
68+
use core::ops::CoerceUnsized;
69+
6570
/// A value that represents the heap. This is the default place that the `box`
6671
/// keyword allocates into when no place is supplied.
6772
///
@@ -390,3 +395,6 @@ impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
390395
self.call_box(args)
391396
}
392397
}
398+
399+
#[cfg(not(stage0))] // SNAP c64d671
400+
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
@@ -193,6 +193,13 @@ extern "rust-intrinsic" {
193193
pub fn min_align_of<T>() -> usize;
194194
pub fn pref_align_of<T>() -> usize;
195195

196+
#[cfg(not(stage0))]
197+
pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
198+
#[cfg(not(stage0))]
199+
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
200+
#[cfg(not(stage0))]
201+
pub fn drop_in_place<T: ?Sized>(_: *mut T);
202+
196203
/// Gets a static string slice containing the name of a type.
197204
pub fn type_name<T: ?Sized>() -> &'static str;
198205

src/libcore/marker.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ pub trait Sized {
5353
// Empty.
5454
}
5555

56+
/// Types that can be "unsized" to a dynamically sized type.
57+
#[unstable(feature = "core")]
58+
#[cfg(not(stage0))] // SNAP c64d671
59+
#[lang="unsize"]
60+
pub trait Unsize<T> {
61+
// Empty.
62+
}
63+
5664
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
5765
///
5866
/// 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
@@ -86,6 +86,22 @@ pub fn size_of<T>() -> usize {
8686
unsafe { intrinsics::size_of::<T>() }
8787
}
8888

89+
/// Returns the size of the type that `val` points to in bytes.
90+
///
91+
/// # Examples
92+
///
93+
/// ```
94+
/// use std::mem;
95+
///
96+
/// assert_eq!(4, mem::size_of_val(&5i32));
97+
/// ```
98+
#[cfg(not(stage0))] // SNAP c64d671
99+
#[inline]
100+
#[stable(feature = "rust1", since = "1.0.0")]
101+
pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
102+
unsafe { intrinsics::size_of_val(val) }
103+
}
104+
89105
/// Returns the size of the type that `_val` points to in bytes.
90106
///
91107
/// # Examples
@@ -95,6 +111,7 @@ pub fn size_of<T>() -> usize {
95111
///
96112
/// assert_eq!(4, mem::size_of_val(&5i32));
97113
/// ```
114+
#[cfg(stage0)] // SNAP c64d671
98115
#[inline]
99116
#[stable(feature = "rust1", since = "1.0.0")]
100117
pub fn size_of_val<T>(_val: &T) -> usize {
@@ -118,6 +135,22 @@ pub fn min_align_of<T>() -> usize {
118135
unsafe { intrinsics::min_align_of::<T>() }
119136
}
120137

138+
/// Returns the ABI-required minimum alignment of the type of the value that `val` points to
139+
///
140+
/// # Examples
141+
///
142+
/// ```
143+
/// use std::mem;
144+
///
145+
/// assert_eq!(4, mem::min_align_of_val(&5i32));
146+
/// ```
147+
#[cfg(not(stage0))] // SNAP c64d671
148+
#[inline]
149+
#[stable(feature = "rust1", since = "1.0.0")]
150+
pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
151+
unsafe { intrinsics::min_align_of_val(val) }
152+
}
153+
121154
/// Returns the ABI-required minimum alignment of the type of the value that `_val` points to
122155
///
123156
/// # Examples
@@ -127,6 +160,7 @@ pub fn min_align_of<T>() -> usize {
127160
///
128161
/// assert_eq!(4, mem::min_align_of_val(&5i32));
129162
/// ```
163+
#[cfg(stage0)] // SNAP c64d671
130164
#[inline]
131165
#[stable(feature = "rust1", since = "1.0.0")]
132166
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;
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
pub unsafe trait Zeroable {}
@@ -54,3 +56,6 @@ impl<T: Zeroable> Deref for NonZero<T> {
5456
inner
5557
}
5658
}
59+
60+
#[cfg(not(stage0))] // SNAP c64d671
61+
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
///
@@ -1207,3 +1210,34 @@ mod impls {
12071210
}
12081211
}
12091212
}
1213+
1214+
/// Trait that indicates that this is a pointer or a wrapper for one,
1215+
/// where unsizing can be performed on the pointee.
1216+
#[unstable(feature = "core")]
1217+
#[cfg(not(stage0))] // SNAP c64d671
1218+
#[lang="coerce_unsized"]
1219+
pub trait CoerceUnsized<T> {
1220+
// Empty.
1221+
}
1222+
1223+
#[cfg(not(stage0))] // SNAP c64d671
1224+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
1225+
#[cfg(not(stage0))] // SNAP c64d671
1226+
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
1227+
#[cfg(not(stage0))] // SNAP c64d671
1228+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
1229+
#[cfg(not(stage0))] // SNAP c64d671
1230+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
1231+
1232+
#[cfg(not(stage0))] // SNAP c64d671
1233+
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
1234+
#[cfg(not(stage0))] // SNAP c64d671
1235+
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
1236+
1237+
#[cfg(not(stage0))] // SNAP c64d671
1238+
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
1239+
#[cfg(not(stage0))] // SNAP c64d671
1240+
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
1241+
1242+
#[cfg(not(stage0))] // SNAP c64d671
1243+
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}

src/librustc/diagnostics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,9 @@ register_diagnostics! {
807807
E0017,
808808
E0019,
809809
E0022,
810+
E0038,
811+
E0079, // enum variant: expected signed integer constant
812+
E0080, // enum variant: constant evaluation error
810813
E0109,
811814
E0110,
812815
E0134,

src/librustc/metadata/common.rs

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

261261
pub const tag_defaulted_trait: usize = 0xa4;
262+
263+
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
@@ -279,6 +279,14 @@ pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
279279
decoder::get_impl_polarity(&*cdata, def.node)
280280
}
281281

282+
pub fn get_custom_coerce_unsized_kind<'tcx>(tcx: &ty::ctxt<'tcx>,
283+
def: ast::DefId)
284+
-> Option<ty::CustomCoerceUnsized> {
285+
let cstore = &tcx.sess.cstore;
286+
let cdata = cstore.get_crate_data(def.krate);
287+
decoder::get_custom_coerce_unsized_kind(&*cdata, def.node)
288+
}
289+
282290
// Given a def_id for an impl, return the trait it implements,
283291
// if there is one.
284292
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
@@ -489,6 +489,16 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
489489
}
490490
}
491491

492+
pub fn get_custom_coerce_unsized_kind<'tcx>(cdata: Cmd,
493+
id: ast::NodeId)
494+
-> Option<ty::CustomCoerceUnsized> {
495+
let item_doc = lookup_item(id, cdata.data());
496+
reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
497+
let mut decoder = reader::Decoder::new(kind_doc);
498+
Decodable::decode(&mut decoder).unwrap()
499+
})
500+
}
501+
492502
pub fn get_impl_trait<'tcx>(cdata: Cmd,
493503
id: ast::NodeId,
494504
tcx: &ty::ctxt<'tcx>)

src/librustc/metadata/encoder.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
12191219
encode_attributes(rbml_w, &item.attrs);
12201220
encode_unsafety(rbml_w, unsafety);
12211221
encode_polarity(rbml_w, polarity);
1222+
1223+
match tcx.custom_coerce_unsized_kinds.borrow().get(&local_def(item.id)) {
1224+
Some(&kind) => {
1225+
rbml_w.start_tag(tag_impl_coerce_unsized_kind);
1226+
kind.encode(rbml_w);
1227+
rbml_w.end_tag();
1228+
}
1229+
None => {}
1230+
}
1231+
12221232
match ty.node {
12231233
ast::TyPath(None, ref path) if path.segments.len() == 1 => {
12241234
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
@@ -261,11 +261,14 @@ lets_do_this! {
261261

262262
SendTraitLangItem, "send", send_trait;
263263
SizedTraitLangItem, "sized", sized_trait;
264+
UnsizeTraitLangItem, "unsize", unsize_trait;
264265
CopyTraitLangItem, "copy", copy_trait;
265266
SyncTraitLangItem, "sync", sync_trait;
266267

267268
DropTraitLangItem, "drop", drop_trait;
268269

270+
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait;
271+
269272
AddTraitLangItem, "add", add_trait;
270273
SubTraitLangItem, "sub", sub_trait;
271274
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};
@@ -252,6 +256,54 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
252256
note_obligation_cause(infcx, obligation);
253257
}
254258
}
259+
260+
TraitNotObjectSafe(did) => {
261+
span_err!(infcx.tcx.sess, obligation.cause.span, E0038,
262+
"cannot convert to a trait object because trait `{}` is not object-safe",
263+
ty::item_path_str(infcx.tcx, did));
264+
265+
for violation in object_safety_violations(infcx.tcx, did) {
266+
match violation {
267+
ObjectSafetyViolation::SizedSelf => {
268+
infcx.tcx.sess.span_note(
269+
obligation.cause.span,
270+
"the trait cannot require that `Self : Sized`");
271+
}
272+
273+
ObjectSafetyViolation::SupertraitSelf => {
274+
infcx.tcx.sess.span_note(
275+
obligation.cause.span,
276+
"the trait cannot use `Self` as a type parameter \
277+
in the supertrait listing");
278+
}
279+
280+
ObjectSafetyViolation::Method(method,
281+
MethodViolationCode::StaticMethod) => {
282+
infcx.tcx.sess.span_note(
283+
obligation.cause.span,
284+
&format!("method `{}` has no receiver",
285+
method.name.user_string(infcx.tcx)));
286+
}
287+
288+
ObjectSafetyViolation::Method(method,
289+
MethodViolationCode::ReferencesSelf) => {
290+
infcx.tcx.sess.span_note(
291+
obligation.cause.span,
292+
&format!("method `{}` references the `Self` type \
293+
in its arguments or return type",
294+
method.name.user_string(infcx.tcx)));
295+
}
296+
297+
ObjectSafetyViolation::Method(method,
298+
MethodViolationCode::Generic) => {
299+
infcx.tcx.sess.span_note(
300+
obligation.cause.span,
301+
&format!("method `{}` has generic type parameters",
302+
method.name.user_string(infcx.tcx)));
303+
}
304+
}
305+
}
306+
}
255307
}
256308
}
257309

@@ -403,10 +455,6 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
403455
"only the last field of a struct or enum variant \
404456
may have a dynamically sized type")
405457
}
406-
ObligationCauseCode::ObjectSized => {
407-
span_note!(tcx.sess, cause_span,
408-
"only sized types can be made into objects");
409-
}
410458
ObligationCauseCode::SharedStatic => {
411459
span_note!(tcx.sess, cause_span,
412460
"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
@@ -28,6 +28,7 @@ use util::ppaux::Repr;
2828

2929
pub use self::error_reporting::report_fulfillment_errors;
3030
pub use self::error_reporting::report_overflow_error;
31+
pub use self::error_reporting::report_selection_error;
3132
pub use self::error_reporting::suggest_new_overflow_limit;
3233
pub use self::coherence::orphan_check;
3334
pub use self::coherence::overlapping_impls;
@@ -48,6 +49,7 @@ pub use self::select::{MethodMatchedData}; // intentionally don't export variant
4849
pub use self::util::elaborate_predicates;
4950
pub use self::util::get_vtable_index_of_object_method;
5051
pub use self::util::trait_ref_for_builtin_bound;
52+
pub use self::util::predicate_for_trait_def;
5153
pub use self::util::supertraits;
5254
pub use self::util::Supertraits;
5355
pub use self::util::supertrait_def_ids;
@@ -121,9 +123,6 @@ pub enum ObligationCauseCode<'tcx> {
121123
// Types of fields (other than the last) in a struct must be sized.
122124
FieldSized,
123125

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

@@ -159,6 +158,7 @@ pub enum SelectionError<'tcx> {
159158
OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
160159
ty::PolyTraitRef<'tcx>,
161160
ty::type_err<'tcx>),
161+
TraitNotObjectSafe(ast::DefId),
162162
}
163163

164164
pub struct FulfillmentError<'tcx> {
@@ -536,7 +536,9 @@ impl<'tcx, N> Vtable<'tcx, N> {
536536
}
537537
}
538538

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

0 commit comments

Comments
 (0)