diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 31621c72f6595..da4bc4dbc7694 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -896,8 +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::AutoUnsafe(_, 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 diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 87b6213694a29..9c58a4c79f057 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -157,16 +157,19 @@ fn get_base_type_def_id(inference_context: &InferCtxt, ty_unboxed_closure(def_id, _) => { Some(def_id) } - 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) - } - _ => { - fail!("get_base_type() returned a type that wasn't an \ - enum, struct, or trait"); + 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) + } + _ => { + fail!("get_base_type() returned a type that wasn't an \ + enum, struct, or trait"); + } } - }, + } ty_trait(box ty::TyTrait { def_id, .. }) => { Some(def_id) } diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index acfe588c680ad..381c47279e390 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -350,8 +350,7 @@ 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)) => { + (&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)) => { @@ -478,40 +477,18 @@ impl<'f> Coerce<'f> { b.repr(tcx)); let coercion = Coercion(self.get_ref().trace.clone()); + let r_a = self.get_ref().infcx.next_region_var(coercion); - 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, - ref substs, - bounds, - .. - }) => { - let tr = ty::mk_trait(tcx, def_id, substs.clone(), bounds); - 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)) - }))) - } - _ => { - self.subtype(a, b) - } - }, - _ => { - self.subtype(a, b) - } - } + self.coerce_object(a, sty_a, b, + |tr| ty::mk_rptr(tcx, r_a, ty::mt{ mutbl: b_mutbl, ty: tr }), + || 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 + a: ty::t, + sty_a: &ty::sty, + b: ty::t, + b_mutbl: ast::Mutability) -> CoerceResult { let tcx = self.get_ref().infcx.tcx; @@ -519,9 +496,22 @@ impl<'f> Coerce<'f> { a.repr(tcx), sty_a, b.repr(tcx)); + self.coerce_object(a, sty_a, b, + |tr| ty::mk_ptr(tcx, ty::mt{ mutbl: b_mutbl, ty: tr }), + || AutoUnsafe(b_mutbl, None)) + } + + fn coerce_object(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t, + mk_ty: |ty::t| -> ty::t, + mk_adjust: || -> ty::AutoRef) -> CoerceResult + { + let tcx = self.get_ref().infcx.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_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty { ty::ty_trait(box ty::TyTrait { def_id, ref substs, @@ -529,12 +519,10 @@ impl<'f> Coerce<'f> { .. }) => { 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)); + try!(self.subtype(mk_ty(tr), b)); Ok(Some(AutoDerefRef(AutoDerefRef { autoderefs: 1, - autoref: Some(AutoUnsafe(b_mutbl, None)) + autoref: Some(mk_adjust()) }))) } _ => { diff --git a/src/test/compile-fail/dst-bad-coercions.rs b/src/test/compile-fail/dst-bad-coercions.rs index b1bea2cb57fc2..cc5d3b520f95c 100644 --- a/src/test/compile-fail/dst-bad-coercions.rs +++ b/src/test/compile-fail/dst-bad-coercions.rs @@ -8,21 +8,44 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test implicit coercions involving DSTs and raw pointers. + struct S; trait T {} impl T for S {} +struct Foo { + f: T +} + pub fn main() { + // Test that we cannot convert from *-ptr to &-ptr 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 y: &S = x; //~ ERROR mismatched types + let y: &T = x; //~ ERROR mismatched types + // Test that we cannot convert from *-ptr to &-ptr (mut version) 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 y: &S = x; //~ ERROR mismatched types + let y: &T = x; //~ ERROR mismatched types + // Test that we cannot convert an immutable ptr to a mutable one using *-ptrs 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) -} \ No newline at end of file + //~^ ERROR mismatched types + + // The below four sets of tests test that we cannot implicitly deref a *-ptr + // during a coercion. + let x: *const S = &S; + let y: *const T = x; //~ ERROR mismatched types + + let x: *mut S = &mut S; + let y: *mut T = x; //~ ERROR mismatched types + + let x: *const Foo = &Foo {f: S}; + let y: *const Foo = x; //~ ERROR mismatched types + + let x: *mut Foo = &mut Foo {f: S}; + let y: *mut Foo = x; //~ ERROR mismatched types +} diff --git a/src/test/run-fail/dst-raw-slice.rs b/src/test/run-fail/dst-raw-slice.rs new file mode 100644 index 0000000000000..39bf899a023f1 --- /dev/null +++ b/src/test/run-fail/dst-raw-slice.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test bounds checking for DST raw slices +// error-pattern:index out of bounds + +fn main() { + let a: *const [_] = &[1i, 2, 3]; + unsafe { + let _b = (*a)[3]; + } +} diff --git a/src/test/run-pass/dst-coercions.rs b/src/test/run-pass/dst-coercions.rs index 1b3776c86a2c0..1c9d5cd3afe4d 100644 --- a/src/test/run-pass/dst-coercions.rs +++ b/src/test/run-pass/dst-coercions.rs @@ -8,21 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test coercions involving DST and/or raw pointers + struct S; trait T {} impl T for S {} pub fn main() { let x: &T = &S; + // Test we can convert from &-ptr to *-ptr of trait objects let x: *const T = &S; + // Test we can convert from &-ptr to *-ptr of struct pointer (not DST) let x: *const S = &S; + // As above, but mut let x: &mut T = &mut S; let x: *mut T = &mut S; let x: *mut S = &mut S; + // Test we can chnage the mutability from mut to const. let x: &T = &mut S; let x: *const T = &mut S; -} \ No newline at end of file +} diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index 21c29f1637e4c..a977e961b1352 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -23,15 +23,14 @@ impl Trait for A { } } -pub struct Foo { +struct Foo { f: T } pub fn main() { // raw trait object let x = A { f: 42 }; - let y: *const A = &x; - let z: *const Trait = y; + let z: *const Trait = &x; let r = unsafe { (&*z).foo() }; @@ -39,8 +38,7 @@ pub fn main() { // raw DST struct let p = Foo {f: A { f: 42 }}; - let q: *const Foo = &p; - let o: *const Foo = q; + let o: *const Foo = &p; let r = unsafe { (&*o).f.foo() }; @@ -51,6 +49,8 @@ pub fn main() { unsafe { let b = (*a)[2]; assert!(b == 3); + let len = (*a).len(); + assert!(len == 3); } // raw DST struct with slice @@ -58,20 +58,20 @@ pub fn main() { unsafe { let b = (&*c).f[0]; assert!(b == 1); + let len = (&*c).f.len(); + assert!(len == 3); } // all of the above with *mut let mut x = A { f: 42 }; - let y: *mut A = &mut x; - let z: *mut Trait = y; + let z: *mut Trait = &mut x; let r = unsafe { (&*z).foo() }; assert!(r == 42); let mut p = Foo {f: A { f: 42 }}; - let q: *mut Foo = &mut p; - let o: *mut Foo = q; + let o: *mut Foo = &mut p; let r = unsafe { (&*o).f.foo() }; @@ -81,11 +81,15 @@ pub fn main() { unsafe { let b = (*a)[2]; assert!(b == 3); + let len = (*a).len(); + assert!(len == 3); } let c: *mut Foo<[_]> = &mut Foo {f: [1i, 2, 3]}; unsafe { let b = (&*c).f[0]; assert!(b == 1); + let len = (&*c).f.len(); + assert!(len == 3); } } \ No newline at end of file