diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs index 1d1ee39d6843..e268160a42b8 100644 --- a/src/librustc/middle/infer/coercion.rs +++ b/src/librustc/middle/infer/coercion.rs @@ -552,17 +552,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { b.repr(self.get_ref().infcx.tcx)); let mt_a = match *sty_a { - ty::ty_rptr(_, mt) => mt, + ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => mt, _ => { return self.subtype(a, b); } }; // 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); + let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, ty::mt{ mutbl: mutbl_b, ty: mt_a.ty }); try!(self.subtype(a_unsafe, b)); + if !can_coerce_mutbls(mt_a.mutbl, mutbl_b) { + return Err(ty::terr_mutability); + } // Although references and unsafe ptrs have the same // representation, we still register an AutoDerefRef so that diff --git a/src/test/compile-fail/ptr-coercion.rs b/src/test/compile-fail/ptr-coercion.rs new file mode 100644 index 000000000000..d9b20748a7a2 --- /dev/null +++ b/src/test/compile-fail/ptr-coercion.rs @@ -0,0 +1,24 @@ +// 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 coercions between pointers which don't do anything fancy like unsizing. +// These are testing that we don't lose mutability when converting to raw pointers. + +pub fn main() { + // *const -> *mut + let x: *const int = &42i; + let x: *mut int = x; //~ERROR values differ in mutability + + // & -> *mut + let x: *mut int = &42; //~ERROR values differ in mutability + + let x: *const int = &42; + let x: *mut int = x; //~ERROR values differ in mutability +} diff --git a/src/test/run-pass/ptr-coercion.rs b/src/test/run-pass/ptr-coercion.rs new file mode 100644 index 000000000000..1b77c1316ed2 --- /dev/null +++ b/src/test/run-pass/ptr-coercion.rs @@ -0,0 +1,35 @@ +// 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 coercions between pointers which don't do anything fancy like unsizing. + +pub fn main() { + // &mut -> & + let x: &mut int = &mut 42i; + let x: &int = x; + + let x: &int = &mut 42i; + + // & -> *const + let x: &int = &42i; + let x: *const int = x; + + let x: *const int = &42i; + + // &mut -> *const + let x: &mut int = &mut 42i; + let x: *const int = x; + + let x: *const int = &mut 42i; + + // *mut -> *const + let x: *mut int = &mut 42i; + let x: *const int = x; +}