DST raw pointers - *-pointers are fat pointers
This commit is contained in:
parent
01364c44a4
commit
52d6d3be48
@ -170,5 +170,6 @@ register_diagnostics!(
|
||||
E0156,
|
||||
E0157,
|
||||
E0158,
|
||||
E0159
|
||||
E0159,
|
||||
E0160
|
||||
)
|
||||
|
@ -1073,9 +1073,18 @@ impl<'a> rbml_writer_helpers for Encoder<'a> {
|
||||
this.emit_enum_variant_arg(0, |this| Ok(this.emit_unsize_kind(ecx, uk)))
|
||||
})
|
||||
}
|
||||
&ty::AutoUnsafe(m) => {
|
||||
this.emit_enum_variant("AutoUnsafe", 3, 1, |this| {
|
||||
this.emit_enum_variant_arg(0, |this| m.encode(this))
|
||||
&ty::AutoUnsafe(m, None) => {
|
||||
this.emit_enum_variant("AutoUnsafe", 3, 2, |this| {
|
||||
this.emit_enum_variant_arg(0, |this| m.encode(this));
|
||||
this.emit_enum_variant_arg(1,
|
||||
|this| this.emit_option(|this| this.emit_option_none()))
|
||||
})
|
||||
}
|
||||
&ty::AutoUnsafe(m, Some(box ref a)) => {
|
||||
this.emit_enum_variant("AutoUnsafe", 3, 2, |this| {
|
||||
this.emit_enum_variant_arg(0, |this| m.encode(this));
|
||||
this.emit_enum_variant_arg(1, |this| this.emit_option(
|
||||
|this| this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a)))))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1635,8 +1644,16 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
|
||||
3 => {
|
||||
let m: ast::Mutability =
|
||||
this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
|
||||
let a: Option<Box<ty::AutoRef>> =
|
||||
this.read_enum_variant_arg(1, |this| this.read_option(|this, b| {
|
||||
if b {
|
||||
Ok(Some(box this.read_autoref(xcx)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
})).unwrap();
|
||||
|
||||
ty::AutoUnsafe(m)
|
||||
ty::AutoUnsafe(m, a)
|
||||
}
|
||||
_ => fail!("bad enum variant for ty::AutoRef")
|
||||
})
|
||||
|
@ -762,7 +762,7 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
|
||||
ty::BorrowKind::from_mutbl(m),
|
||||
AutoRef);
|
||||
}
|
||||
ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) | ty::AutoUnsafe(_) => {}
|
||||
ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) | ty::AutoUnsafe(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,8 +296,9 @@ impl Case {
|
||||
|
||||
for (i, &ty) in self.tys.iter().enumerate() {
|
||||
match ty::get(ty).sty {
|
||||
// &T/&mut T could either be a thin or fat pointer depending on T
|
||||
ty::ty_rptr(_, ty::mt { ty, .. }) => match ty::get(ty).sty {
|
||||
// &T/&mut T/*T could either be a thin or fat pointer depending on T
|
||||
ty::ty_rptr(_, ty::mt { ty, .. })
|
||||
| ty::ty_ptr(ty::mt { ty, .. }) => match ty::get(ty).sty {
|
||||
// &[T] and &str are a pointer and length pair
|
||||
ty::ty_vec(_, None) | ty::ty_str => return Some(FatPointer(i, slice_elt_base)),
|
||||
|
||||
|
@ -566,8 +566,8 @@ pub fn compare_scalar_types<'a>(
|
||||
|
||||
match ty::get(t).sty {
|
||||
ty::ty_nil => f(nil_type),
|
||||
ty::ty_bool | ty::ty_ptr(_) |
|
||||
ty::ty_uint(_) | ty::ty_char => f(unsigned_int),
|
||||
ty::ty_bool | ty::ty_uint(_) | ty::ty_char => f(unsigned_int),
|
||||
ty::ty_ptr(mt) if ty::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int),
|
||||
ty::ty_int(_) => f(signed_int),
|
||||
ty::ty_float(_) => f(floating_point),
|
||||
// Should never get here, because t is scalar.
|
||||
|
@ -243,7 +243,7 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
|
||||
}
|
||||
Some(ref autoref) => {
|
||||
match *autoref {
|
||||
ty::AutoUnsafe(_) |
|
||||
ty::AutoUnsafe(_, None) |
|
||||
ty::AutoPtr(ty::ReStatic, _, None) => {
|
||||
// Don't copy data to do a deref+ref
|
||||
// (i.e., skip the last auto-deref).
|
||||
|
@ -254,11 +254,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
|
||||
let mut datum = datum;
|
||||
|
||||
let datum = match autoref {
|
||||
&AutoUnsafe(..) => {
|
||||
debug!(" AutoUnsafe");
|
||||
unpack_datum!(bcx, ref_ptr(bcx, expr, datum))
|
||||
}
|
||||
&AutoPtr(_, _, ref a) => {
|
||||
&AutoPtr(_, _, ref a) | &AutoUnsafe(_, ref a) => {
|
||||
debug!(" AutoPtr");
|
||||
match a {
|
||||
&Some(box ref a) => datum = unpack_datum!(bcx,
|
||||
@ -1847,8 +1843,7 @@ pub fn cast_type_kind(tcx: &ty::ctxt, t: ty::t) -> cast_kind {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_char => cast_integral,
|
||||
ty::ty_float(..) => cast_float,
|
||||
ty::ty_ptr(..) => cast_pointer,
|
||||
ty::ty_rptr(_, mt) => {
|
||||
ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => {
|
||||
if ty::type_is_sized(tcx, mt.ty) {
|
||||
cast_pointer
|
||||
} else {
|
||||
|
@ -154,7 +154,7 @@ impl<'a, 'b> Reflector<'a, 'b> {
|
||||
// Unfortunately we can't do anything here because at runtime we
|
||||
// pass around the value by pointer (*u8). But unsized pointers are
|
||||
// fat and so we can't just cast them to *u8 and back. So we have
|
||||
// to work with the pointer directly (see ty_rptr/ty_uniq).
|
||||
// to work with the pointer directly (see ty_ptr/ty_rptr/ty_uniq).
|
||||
fail!("Can't reflect unsized type")
|
||||
}
|
||||
// FIXME(15049) Reflection for unsized structs.
|
||||
@ -177,8 +177,24 @@ impl<'a, 'b> Reflector<'a, 'b> {
|
||||
self.visit("box", extra.as_slice())
|
||||
}
|
||||
ty::ty_ptr(ref mt) => {
|
||||
let extra = self.c_mt(mt);
|
||||
self.visit("ptr", extra.as_slice())
|
||||
match ty::get(mt.ty).sty {
|
||||
ty::ty_vec(ty, None) => {
|
||||
let extra = self.c_mt(&ty::mt{ty: ty, mutbl: mt.mutbl});
|
||||
self.visit("evec_slice", extra.as_slice())
|
||||
}
|
||||
ty::ty_str => self.visit("estr_slice", &[]),
|
||||
ty::ty_trait(..) => {
|
||||
let extra = [
|
||||
self.c_slice(token::intern_and_get_ident(
|
||||
ty_to_string(tcx, t).as_slice()))
|
||||
];
|
||||
self.visit("trait", extra);
|
||||
}
|
||||
_ => {
|
||||
let extra = self.c_mt(mt);
|
||||
self.visit("ptr", extra.as_slice())
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ty_uniq(typ) => {
|
||||
match ty::get(typ).sty {
|
||||
|
@ -174,9 +174,8 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
|
||||
ty::ty_float(t) => Type::float_from_ty(cx, t),
|
||||
|
||||
ty::ty_box(..) |
|
||||
ty::ty_ptr(..) => Type::i8p(cx),
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
|
||||
ty::ty_box(..) => Type::i8p(cx),
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
|
||||
if ty::type_is_sized(cx.tcx(), ty) {
|
||||
Type::i8p(cx)
|
||||
} else {
|
||||
@ -303,9 +302,8 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
|
||||
ty::ty_box(typ) => {
|
||||
Type::at_box(cx, type_of(cx, typ)).ptr_to()
|
||||
}
|
||||
ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
|
||||
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_str => {
|
||||
// This means we get a nicer name in the output (str is always
|
||||
|
@ -298,7 +298,8 @@ pub enum AutoRef {
|
||||
|
||||
/// Convert from T to *T
|
||||
/// Value to thin pointer
|
||||
AutoUnsafe(ast::Mutability),
|
||||
/// The second field allows us to wrap other AutoRef adjustments.
|
||||
AutoUnsafe(ast::Mutability, Option<Box<AutoRef>>),
|
||||
}
|
||||
|
||||
// Ugly little helper function. The first bool in the returned tuple is true if
|
||||
@ -326,6 +327,7 @@ fn autoref_object_region(autoref: &AutoRef) -> (bool, bool, Option<Region>) {
|
||||
(b, u, Some(adj_r))
|
||||
}
|
||||
}
|
||||
&AutoUnsafe(_, Some(box ref autoref)) => autoref_object_region(autoref),
|
||||
_ => (false, false, None)
|
||||
}
|
||||
}
|
||||
@ -380,6 +382,12 @@ pub fn type_of_adjust(cx: &ctxt, adj: &AutoAdjustment) -> Option<t> {
|
||||
None => None
|
||||
}
|
||||
}
|
||||
&AutoUnsafe(m, Some(box ref autoref)) => {
|
||||
match type_of_autoref(cx, autoref) {
|
||||
Some(t) => Some(mk_ptr(cx, mt {mutbl: m, ty: t})),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
@ -1898,7 +1906,7 @@ pub fn type_is_self(ty: t) -> bool {
|
||||
|
||||
fn type_is_slice(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_rptr(_, mt) => match get(mt.ty).sty {
|
||||
ty_ptr(mt) | ty_rptr(_, mt) => match get(mt.ty).sty {
|
||||
ty_vec(_, None) | ty_str => true,
|
||||
_ => false,
|
||||
},
|
||||
@ -1996,7 +2004,8 @@ pub fn type_is_unique(ty: t) -> bool {
|
||||
|
||||
pub fn type_is_fat_ptr(cx: &ctxt, ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_rptr(_, mt{ty, ..}) | ty_uniq(ty) if !type_is_sized(cx, ty) => true,
|
||||
ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..})
|
||||
| ty_uniq(ty) if !type_is_sized(cx, ty) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -2896,7 +2905,7 @@ pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability {
|
||||
|
||||
pub fn type_is_trait(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) => match get(ty).sty {
|
||||
ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match get(ty).sty {
|
||||
ty_trait(..) => true,
|
||||
_ => false
|
||||
},
|
||||
@ -3392,8 +3401,12 @@ pub fn adjust_ty(cx: &ctxt,
|
||||
})
|
||||
}
|
||||
|
||||
AutoUnsafe(m) => {
|
||||
mk_ptr(cx, mt {ty: ty, mutbl: m})
|
||||
AutoUnsafe(m, ref a) => {
|
||||
let adjusted_ty = match a {
|
||||
&Some(box ref a) => adjust_for_autoref(cx, span, ty, a),
|
||||
&None => ty
|
||||
};
|
||||
mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
|
||||
}
|
||||
|
||||
AutoUnsize(ref k) => unsize_ty(cx, ty, k, span),
|
||||
@ -3444,7 +3457,8 @@ impl AutoRef {
|
||||
ty::AutoPtr(r, m, Some(ref a)) => ty::AutoPtr(f(r), m, Some(box a.map_region(f))),
|
||||
ty::AutoUnsize(ref k) => ty::AutoUnsize(k.clone()),
|
||||
ty::AutoUnsizeUniq(ref k) => ty::AutoUnsizeUniq(k.clone()),
|
||||
ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
|
||||
ty::AutoUnsafe(m, None) => ty::AutoUnsafe(m, None),
|
||||
ty::AutoUnsafe(m, Some(ref a)) => ty::AutoUnsafe(m, Some(box a.map_region(f))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -466,7 +466,10 @@ pub fn super_fold_autoref<T:TypeFolder>(this: &mut T,
|
||||
ty::AutoPtr(r, m, Some(ref a)) => {
|
||||
ty::AutoPtr(this.fold_region(r), m, Some(box super_fold_autoref(this, &**a)))
|
||||
}
|
||||
ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
|
||||
ty::AutoUnsafe(m, None) => ty::AutoUnsafe(m, None),
|
||||
ty::AutoUnsafe(m, Some(ref a)) => {
|
||||
ty::AutoUnsafe(m, Some(box super_fold_autoref(this, &**a)))
|
||||
}
|
||||
ty::AutoUnsize(ref k) => ty::AutoUnsize(k.fold_with(this)),
|
||||
ty::AutoUnsizeUniq(ref k) => ty::AutoUnsizeUniq(k.fold_with(this)),
|
||||
}
|
||||
|
@ -3650,7 +3650,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
ast::ExprAddrOf(mutbl, ref oprnd) => {
|
||||
let expected = expected.only_has_type();
|
||||
let hint = expected.map(fcx, |sty| {
|
||||
match *sty { ty::ty_rptr(_, ref mt) => ExpectHasType(mt.ty),
|
||||
match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
|
||||
_ => NoExpectation }
|
||||
});
|
||||
let lvalue_pref = match mutbl {
|
||||
|
@ -1363,7 +1363,7 @@ fn link_autoref(rcx: &Rcx,
|
||||
ty::BorrowKind::from_mutbl(m), expr_cmt);
|
||||
}
|
||||
|
||||
ty::AutoUnsafe(_) | ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) => {}
|
||||
ty::AutoUnsafe(..) | ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,9 +630,13 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
|
||||
let cx = fcx.ccx;
|
||||
let check_object_cast = |src_ty: ty::t, target_ty: ty::t| {
|
||||
debug!("check_object_cast {} to {}",
|
||||
fcx.infcx().ty_to_string(src_ty),
|
||||
fcx.infcx().ty_to_string(target_ty));
|
||||
// Check that a cast is of correct types.
|
||||
match (&ty::get(target_ty).sty, &ty::get(src_ty).sty) {
|
||||
(&ty::ty_rptr(_, ty::mt{ty, mutbl}), &ty::ty_rptr(_, mt))
|
||||
| (&ty::ty_ptr(ty::mt{ty, mutbl}), &ty::ty_rptr(_, mt))
|
||||
if !mutability_allowed(mt.mutbl, mutbl) => {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_trait(..) => {
|
||||
@ -641,7 +645,9 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
(&ty::ty_uniq(..), &ty::ty_uniq(..) ) => {}
|
||||
(&ty::ty_uniq(..), &ty::ty_uniq(..) )
|
||||
| (&ty::ty_ptr(..), &ty::ty_ptr(..) )
|
||||
| (&ty::ty_ptr(..), &ty::ty_rptr(..)) => {}
|
||||
(&ty::ty_rptr(r_t, _), &ty::ty_rptr(r_s, _)) => {
|
||||
infer::mk_subr(fcx.infcx(),
|
||||
infer::RelateObjectBound(ex.span),
|
||||
@ -669,6 +675,16 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
(&ty::ty_ptr(ty::mt{ty, ..}), _) => {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_trait(..) => {
|
||||
span_err!(fcx.ccx.tcx.sess, ex.span, E0160,
|
||||
"can only cast an *-pointer or &-pointer to an *-object, not a {}",
|
||||
ty::ty_sort_string(fcx.tcx(), src_ty));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
@ -880,7 +896,8 @@ fn trait_cast_types(fcx: &FnCtxt,
|
||||
match autoref {
|
||||
&ty::AutoUnsize(ref k) |
|
||||
&ty::AutoUnsizeUniq(ref k) => trait_cast_types_unsize(fcx, k, src_ty, sp),
|
||||
&ty::AutoPtr(_, _, Some(box ref autoref)) => {
|
||||
&ty::AutoPtr(_, _, Some(box ref autoref))
|
||||
| &ty::AutoUnsafe(_, Some(box ref autoref))=> {
|
||||
trait_cast_types_autoref(fcx, autoref, src_ty, sp)
|
||||
}
|
||||
_ => None
|
||||
@ -891,7 +908,7 @@ fn trait_cast_types(fcx: &FnCtxt,
|
||||
&ty::AutoDerefRef(AutoDerefRef{autoref: Some(ref autoref), autoderefs}) => {
|
||||
let mut derefed_type = src_ty;
|
||||
for _ in range(0, autoderefs) {
|
||||
derefed_type = ty::deref(derefed_type, false).unwrap().ty;
|
||||
derefed_type = ty::deref(derefed_type, true).unwrap().ty;
|
||||
derefed_type = structurally_resolved_type(fcx, sp, derefed_type)
|
||||
}
|
||||
trait_cast_types_autoref(fcx, autoref, derefed_type, sp)
|
||||
|
@ -157,7 +157,8 @@ fn get_base_type_def_id(inference_context: &InferCtxt,
|
||||
ty_unboxed_closure(def_id, _) => {
|
||||
Some(def_id)
|
||||
}
|
||||
ty_rptr(_, ty::mt {ty, ..}) | ty_uniq(ty) => match ty::get(ty).sty {
|
||||
ty_ptr(ty::mt {ty, ..}) | ty_rptr(_, ty::mt {ty, ..}) | ty_uniq(ty)
|
||||
=> match ty::get(ty).sty {
|
||||
ty_trait(box ty::TyTrait { def_id, .. }) => {
|
||||
Some(def_id)
|
||||
}
|
||||
|
@ -1401,7 +1401,7 @@ fn check_method_self_type<RS:RegionScope>(
|
||||
ast::SelfExplicit(ref ast_type, _) => {
|
||||
let typ = crate_context.to_ty(rs, &**ast_type);
|
||||
let base_type = match ty::get(typ).sty {
|
||||
ty::ty_rptr(_, tm) => tm.ty,
|
||||
ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
|
||||
ty::ty_uniq(typ) => typ,
|
||||
_ => typ,
|
||||
};
|
||||
|
@ -65,7 +65,7 @@ we may want to adjust precisely when coercions occur.
|
||||
*/
|
||||
|
||||
use middle::subst;
|
||||
use middle::ty::{AutoPtr, AutoDerefRef, AutoUnsize};
|
||||
use middle::ty::{AutoPtr, AutoDerefRef, AutoUnsize, AutoUnsafe};
|
||||
use middle::ty::{mt};
|
||||
use middle::ty;
|
||||
use middle::typeck::infer::{CoerceResult, resolve_type, Coercion};
|
||||
@ -100,7 +100,7 @@ impl<'f> Coerce<'f> {
|
||||
// to `&[T]`. Doing it all at once makes the target code a bit more
|
||||
// efficient and spares us from having to handle multiple coercions.
|
||||
match ty::get(b).sty {
|
||||
ty::ty_rptr(_, mt_b) => {
|
||||
ty::ty_ptr(mt_b) | ty::ty_rptr(_, mt_b) => {
|
||||
match ty::get(mt_b.ty).sty {
|
||||
ty::ty_vec(_, None) => {
|
||||
let unsize_and_ref = self.unpack_actual_value(a, |sty_a| {
|
||||
@ -129,6 +129,33 @@ impl<'f> Coerce<'f> {
|
||||
// Note: does not attempt to resolve type variables we encounter.
|
||||
// See above for details.
|
||||
match ty::get(b).sty {
|
||||
ty::ty_ptr(mt_b) => {
|
||||
match ty::get(mt_b.ty).sty {
|
||||
ty::ty_str => {
|
||||
return self.unpack_actual_value(a, |sty_a| {
|
||||
self.coerce_unsafe_ptr(a, sty_a, b, ast::MutImmutable)
|
||||
});
|
||||
}
|
||||
|
||||
ty::ty_trait(..) => {
|
||||
let result = self.unpack_actual_value(a, |sty_a| {
|
||||
self.coerce_unsafe_object(a, sty_a, b, mt_b.mutbl)
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(t) => return Ok(t),
|
||||
Err(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
return self.unpack_actual_value(a, |sty_a| {
|
||||
self.coerce_unsafe_ptr(a, sty_a, b, mt_b.mutbl)
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ty::ty_rptr(_, mt_b) => {
|
||||
match ty::get(mt_b.ty).sty {
|
||||
ty::ty_str => {
|
||||
@ -165,12 +192,6 @@ impl<'f> Coerce<'f> {
|
||||
});
|
||||
}
|
||||
|
||||
ty::ty_ptr(mt_b) => {
|
||||
return self.unpack_actual_value(a, |sty_a| {
|
||||
self.coerce_unsafe_ptr(a, sty_a, b, mt_b)
|
||||
});
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -329,6 +350,26 @@ impl<'f> Coerce<'f> {
|
||||
}
|
||||
})
|
||||
}
|
||||
(&ty::ty_ptr(ty::mt{ty: t_a, ..}), &ty::ty_ptr(mt_b))
|
||||
| (&ty::ty_rptr(_, ty::mt{ty: t_a, ..}), &ty::ty_ptr(mt_b)) => {
|
||||
self.unpack_actual_value(t_a, |sty_a| {
|
||||
match self.unsize_ty(sty_a, mt_b.ty) {
|
||||
Some((ty, kind)) => {
|
||||
let ty = ty::mk_ptr(self.get_ref().infcx.tcx,
|
||||
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
||||
try!(self.get_ref().infcx.try(|| sub.tys(ty, b)));
|
||||
debug!("Success, coerced with AutoDerefRef(1, \
|
||||
AutoPtr(AutoUnsize({:?})))", kind);
|
||||
Ok(Some(AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
|
||||
Some(box AutoUnsize(kind))))
|
||||
})))
|
||||
}
|
||||
_ => Err(ty::terr_mismatch)
|
||||
}
|
||||
})
|
||||
}
|
||||
(&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
|
||||
self.unpack_actual_value(t_a, |sty_a| {
|
||||
match self.unsize_ty(sty_a, t_b) {
|
||||
@ -357,7 +398,7 @@ impl<'f> Coerce<'f> {
|
||||
sty_a: &ty::sty,
|
||||
ty_b: ty::t)
|
||||
-> Option<(ty::t, ty::UnsizeKind)> {
|
||||
debug!("unsize_ty(sty_a={:?}", sty_a);
|
||||
debug!("unsize_ty(sty_a={:?}, ty_b={})", sty_a, ty_b.repr(self.get_ref().infcx.tcx));
|
||||
|
||||
let tcx = self.get_ref().infcx.tcx;
|
||||
|
||||
@ -430,15 +471,15 @@ impl<'f> Coerce<'f> {
|
||||
b: ty::t,
|
||||
b_mutbl: ast::Mutability) -> CoerceResult
|
||||
{
|
||||
debug!("coerce_borrowed_object(a={}, sty_a={:?}, b={})",
|
||||
a.repr(self.get_ref().infcx.tcx), sty_a,
|
||||
b.repr(self.get_ref().infcx.tcx));
|
||||
|
||||
let tcx = self.get_ref().infcx.tcx;
|
||||
let coercion = Coercion(self.get_ref().trace.clone());
|
||||
let r_a = self.get_ref().infcx.next_region_var(coercion);
|
||||
|
||||
let a_borrowed = match *sty_a {
|
||||
debug!("coerce_borrowed_object(a={}, sty_a={:?}, b={})",
|
||||
a.repr(tcx), sty_a,
|
||||
b.repr(tcx));
|
||||
|
||||
let coercion = Coercion(self.get_ref().trace.clone());
|
||||
|
||||
match *sty_a {
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
|
||||
ty::ty_trait(box ty::TyTrait {
|
||||
def_id,
|
||||
@ -447,22 +488,63 @@ impl<'f> Coerce<'f> {
|
||||
..
|
||||
}) => {
|
||||
let tr = ty::mk_trait(tcx, def_id, substs.clone(), bounds);
|
||||
ty::mk_rptr(tcx, r_a, ty::mt{ mutbl: b_mutbl, ty: tr })
|
||||
let r_a = self.get_ref().infcx.next_region_var(coercion);
|
||||
let a_borrowed = ty::mk_rptr(tcx, r_a, ty::mt{ mutbl: b_mutbl, ty: tr });
|
||||
|
||||
try!(self.subtype(a_borrowed, b));
|
||||
Ok(Some(AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(AutoPtr(r_a, b_mutbl, None))
|
||||
})))
|
||||
}
|
||||
_ => {
|
||||
return self.subtype(a, b);
|
||||
self.subtype(a, b)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return self.subtype(a, b);
|
||||
self.subtype(a, b)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
try!(self.subtype(a_borrowed, b));
|
||||
Ok(Some(AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(AutoPtr(r_a, b_mutbl, None))
|
||||
})))
|
||||
fn coerce_unsafe_object(&self,
|
||||
a: ty::t,
|
||||
sty_a: &ty::sty,
|
||||
b: ty::t,
|
||||
b_mutbl: ast::Mutability) -> CoerceResult
|
||||
{
|
||||
let tcx = self.get_ref().infcx.tcx;
|
||||
|
||||
debug!("coerce_unsafe_object(a={}, sty_a={:?}, b={})",
|
||||
a.repr(tcx), sty_a,
|
||||
b.repr(tcx));
|
||||
|
||||
match *sty_a {
|
||||
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) |
|
||||
ty::ty_ptr(ty::mt{ty, ..}) => match ty::get(ty).sty {
|
||||
ty::ty_trait(box ty::TyTrait {
|
||||
def_id,
|
||||
ref substs,
|
||||
bounds,
|
||||
..
|
||||
}) => {
|
||||
let tr = ty::mk_trait(tcx, def_id, substs.clone(), bounds);
|
||||
let a_raw = ty::mk_ptr(tcx, ty::mt{ mutbl: b_mutbl, ty: tr });
|
||||
|
||||
try!(self.subtype(a_raw, b));
|
||||
Ok(Some(AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(AutoUnsafe(b_mutbl, None))
|
||||
})))
|
||||
}
|
||||
_ => {
|
||||
self.subtype(a, b)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
self.subtype(a, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn coerce_borrowed_fn(&self,
|
||||
@ -521,7 +603,7 @@ impl<'f> Coerce<'f> {
|
||||
a: ty::t,
|
||||
sty_a: &ty::sty,
|
||||
b: ty::t,
|
||||
mt_b: ty::mt)
|
||||
mutbl_b: ast::Mutability)
|
||||
-> CoerceResult {
|
||||
debug!("coerce_unsafe_ptr(a={}, sty_a={:?}, b={})",
|
||||
a.repr(self.get_ref().infcx.tcx), sty_a,
|
||||
@ -534,16 +616,18 @@ impl<'f> Coerce<'f> {
|
||||
}
|
||||
};
|
||||
|
||||
// check that the types which they point at are compatible
|
||||
// Check that the types which they point at are compatible.
|
||||
// Note that we don't adjust the mutability here. We cannot change
|
||||
// the mutability and the kind of pointer in a single coercion.
|
||||
let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, mt_a);
|
||||
try!(self.subtype(a_unsafe, b));
|
||||
|
||||
// although references and unsafe ptrs have the same
|
||||
// Although references and unsafe ptrs have the same
|
||||
// representation, we still register an AutoDerefRef so that
|
||||
// regionck knows that the region for `a` must be valid here
|
||||
// regionck knows that the region for `a` must be valid here.
|
||||
Ok(Some(AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoUnsafe(mt_b.mutbl))
|
||||
autoref: Some(ty::AutoUnsafe(mutbl_b, None))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
28
src/test/compile-fail/dst-bad-coercions.rs
Normal file
28
src/test/compile-fail/dst-bad-coercions.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct S;
|
||||
trait T {}
|
||||
impl T for S {}
|
||||
|
||||
pub fn main() {
|
||||
let x: *const S = &S;
|
||||
let y: &S = x; //~ ERROR mismatched types: expected `&S`, found `*const S` (expected &-ptr
|
||||
let y: &T = x; //~ ERROR mismatched types: expected `&T`, found `*const S` (expected &-ptr
|
||||
|
||||
let x: *mut S = &mut S;
|
||||
let y: &S = x; //~ ERROR mismatched types: expected `&S`, found `*mut S` (expected &-ptr
|
||||
let y: &T = x; //~ ERROR mismatched types: expected `&T`, found `*mut S` (expected &-ptr
|
||||
|
||||
let x: &mut T = &S; //~ ERROR types differ in mutability
|
||||
let x: *mut T = &S; //~ ERROR types differ in mutability
|
||||
let x: *mut S = &S;
|
||||
//~^ ERROR mismatched types: expected `*mut S`, found `&S` (values differ in mutability)
|
||||
}
|
28
src/test/run-pass/dst-coercions.rs
Normal file
28
src/test/run-pass/dst-coercions.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct S;
|
||||
trait T {}
|
||||
impl T for S {}
|
||||
|
||||
pub fn main() {
|
||||
let x: &T = &S;
|
||||
let x: *const T = &S;
|
||||
|
||||
let x: *const S = &S;
|
||||
|
||||
let x: &mut T = &mut S;
|
||||
let x: *mut T = &mut S;
|
||||
|
||||
let x: *mut S = &mut S;
|
||||
|
||||
let x: &T = &mut S;
|
||||
let x: *const T = &mut S;
|
||||
}
|
91
src/test/run-pass/dst-raw.rs
Normal file
91
src/test/run-pass/dst-raw.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test DST raw pointers
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) -> int;
|
||||
}
|
||||
|
||||
struct A {
|
||||
f: int
|
||||
}
|
||||
impl Trait for A {
|
||||
fn foo(&self) -> int {
|
||||
self.f
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Foo<Sized? T> {
|
||||
f: T
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// raw trait object
|
||||
let x = A { f: 42 };
|
||||
let y: *const A = &x;
|
||||
let z: *const Trait = y;
|
||||
let r = unsafe {
|
||||
(&*z).foo()
|
||||
};
|
||||
assert!(r == 42);
|
||||
|
||||
// raw DST struct
|
||||
let p = Foo {f: A { f: 42 }};
|
||||
let q: *const Foo<A> = &p;
|
||||
let o: *const Foo<Trait> = q;
|
||||
let r = unsafe {
|
||||
(&*o).f.foo()
|
||||
};
|
||||
assert!(r == 42);
|
||||
|
||||
// raw slice
|
||||
let a: *const [_] = &[1i, 2, 3];
|
||||
unsafe {
|
||||
let b = (*a)[2];
|
||||
assert!(b == 3);
|
||||
}
|
||||
|
||||
// raw DST struct with slice
|
||||
let c: *const Foo<[_]> = &Foo {f: [1i, 2, 3]};
|
||||
unsafe {
|
||||
let b = (&*c).f[0];
|
||||
assert!(b == 1);
|
||||
}
|
||||
|
||||
// all of the above with *mut
|
||||
let mut x = A { f: 42 };
|
||||
let y: *mut A = &mut x;
|
||||
let z: *mut Trait = y;
|
||||
let r = unsafe {
|
||||
(&*z).foo()
|
||||
};
|
||||
assert!(r == 42);
|
||||
|
||||
let mut p = Foo {f: A { f: 42 }};
|
||||
let q: *mut Foo<A> = &mut p;
|
||||
let o: *mut Foo<Trait> = q;
|
||||
let r = unsafe {
|
||||
(&*o).f.foo()
|
||||
};
|
||||
assert!(r == 42);
|
||||
|
||||
let a: *mut [_] = &mut [1i, 2, 3];
|
||||
unsafe {
|
||||
let b = (*a)[2];
|
||||
assert!(b == 3);
|
||||
}
|
||||
|
||||
let c: *mut Foo<[_]> = &mut Foo {f: [1i, 2, 3]};
|
||||
unsafe {
|
||||
let b = (&*c).f[0];
|
||||
assert!(b == 1);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user