From 7f72884f1366ee9a46cd2b231c09c5c0e44f7ba3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 29 Aug 2014 15:21:28 +1200 Subject: [PATCH] Remove cross-borrowing for traits. Closes #15349 [breaking-change] Trait objects are no longer implicitly coerced from Box to &T. You must make an explicit coercion using `&*`. --- src/librustc/middle/trans/cleanup.rs | 4 ++-- src/librustc/middle/typeck/infer/coercion.rs | 3 +-- src/librustrt/unwind.rs | 2 +- src/libstd/failure.rs | 2 +- src/libstd/io/stdio.rs | 2 +- src/libsyntax/parse/parser.rs | 6 ++--- src/test/compile-fail/cross-borrow-trait.rs | 22 +++++++++++++++++++ .../regions-close-object-into-object.rs | 8 +++---- src/test/run-pass/cleanup-auto-borrow-obj.rs | 2 +- src/test/run-pass/issue-3794.rs | 2 +- src/test/run-pass/new-box.rs | 2 +- .../regions-early-bound-trait-param.rs | 4 ++-- 12 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 src/test/compile-fail/cross-borrow-trait.rs diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index b36887c80e9..515413e03f0 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -640,7 +640,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> { while !popped_scopes.is_empty() { let mut scope = popped_scopes.pop().unwrap(); - if scope.cleanups.iter().any(|c| cleanup_is_suitable_for(*c, label)) + if scope.cleanups.iter().any(|c| cleanup_is_suitable_for(&**c, label)) { let name = scope.block_name("clean"); debug!("generating cleanups for {}", name); @@ -649,7 +649,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> { None); let mut bcx_out = bcx_in; for cleanup in scope.cleanups.iter().rev() { - if cleanup_is_suitable_for(*cleanup, label) { + if cleanup_is_suitable_for(&**cleanup, label) { bcx_out = cleanup.trans(bcx_out); } } diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 381c47279e3..7763a992c8f 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -327,7 +327,6 @@ impl<'f> Coerce<'f> { let sty_b = &ty::get(b).sty; match (sty_a, sty_b) { - (&ty::ty_uniq(_), &ty::ty_rptr(..)) => Err(ty::terr_mismatch), (&ty::ty_rptr(_, ty::mt{ty: t_a, ..}), &ty::ty_rptr(_, mt_b)) => { self.unpack_actual_value(t_a, |sty_a| { match self.unsize_ty(sty_a, mt_b.ty) { @@ -511,7 +510,7 @@ impl<'f> Coerce<'f> { let tcx = self.get_ref().infcx.tcx; match *sty_a { - ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty { + ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty { ty::ty_trait(box ty::TyTrait { def_id, ref substs, diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs index 9de58960c5e..9e6dff8a751 100644 --- a/src/librustrt/unwind.rs +++ b/src/librustrt/unwind.rs @@ -570,7 +570,7 @@ fn begin_unwind_inner(msg: Box, file_line: &(&'static str, uint)) -> n => { let f: Callback = unsafe { mem::transmute(n) }; let (file, line) = *file_line; - f(msg, file, line); + f(&*msg, file, line); } } }; diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs index 8c709d20d19..8d715de16e6 100644 --- a/src/libstd/failure.rs +++ b/src/libstd/failure.rs @@ -81,7 +81,7 @@ pub fn on_fail(obj: &Any + Send, file: &'static str, line: uint) { "task '{}' failed at '{}', {}:{}\n", n, msg, file, line); if backtrace::log_enabled() { - let _ = backtrace::write(stderr); + let _ = backtrace::write(&mut *stderr); } local_stderr.replace(Some(stderr)); } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index fea161c426a..bd837b6f7b5 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -203,7 +203,7 @@ fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) { let mut my_stdout = local_stdout.replace(None).unwrap_or_else(|| { box stdout() as Box }); - let result = f(my_stdout); + let result = f(&mut *my_stdout); local_stdout.replace(Some(my_stdout)); result } else { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d3700059862..81ac789b683 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -351,7 +351,7 @@ impl<'a> Parser<'a> { mut rdr: Box) -> Parser<'a> { - let tok0 = real_token(rdr); + let tok0 = real_token(&mut *rdr); let span = tok0.sp; let placeholder = TokenAndSpan { tok: token::UNDERSCORE, @@ -899,7 +899,7 @@ impl<'a> Parser<'a> { None }; let next = if self.buffer_start == self.buffer_end { - real_token(self.reader) + real_token(&mut *self.reader) } else { // Avoid token copies with `replace`. let buffer_start = self.buffer_start as uint; @@ -943,7 +943,7 @@ impl<'a> Parser<'a> { -> R { let dist = distance as int; while self.buffer_length() < dist { - self.buffer[self.buffer_end as uint] = real_token(self.reader); + self.buffer[self.buffer_end as uint] = real_token(&mut *self.reader); self.buffer_end = (self.buffer_end + 1) & 3; } f(&self.buffer[((self.buffer_start + dist - 1) & 3) as uint].tok) diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs new file mode 100644 index 00000000000..1ccd5290fef --- /dev/null +++ b/src/test/compile-fail/cross-borrow-trait.rs @@ -0,0 +1,22 @@ +// Copyright 2012-2013-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 that cross-borrowing (implicitly converting from `Box` to `&T`) is +// forbidden when `T` is a trait. + +struct Foo; +trait Trait {} +impl Trait for Foo {} + +pub fn main() { + let x: Box = box Foo; + let _y: &Trait = x; //~ ERROR mismatched types: expected `&Trait`, found `Box` +} + diff --git a/src/test/compile-fail/regions-close-object-into-object.rs b/src/test/compile-fail/regions-close-object-into-object.rs index a45c8e1db54..835c55c9bd1 100644 --- a/src/test/compile-fail/regions-close-object-into-object.rs +++ b/src/test/compile-fail/regions-close-object-into-object.rs @@ -16,19 +16,19 @@ trait X {} impl<'a, T> X for B<'a, T> {} fn f<'a, T, U>(v: Box+'static>) -> Box { - box B(v) as Box + box B(&*v) as Box } fn g<'a, T: 'static>(v: Box>) -> Box { - box B(v) as Box //~ ERROR cannot infer + box B(&*v) as Box //~ ERROR cannot infer } fn h<'a, T, U>(v: Box+'static>) -> Box { - box B(v) as Box + box B(&*v) as Box } fn i<'a, T, U>(v: Box>) -> Box { - box B(v) as Box //~ ERROR cannot infer + box B(&*v) as Box //~ ERROR cannot infer } fn main() {} diff --git a/src/test/run-pass/cleanup-auto-borrow-obj.rs b/src/test/run-pass/cleanup-auto-borrow-obj.rs index 23142082a8c..5d7dbbe5a29 100644 --- a/src/test/run-pass/cleanup-auto-borrow-obj.rs +++ b/src/test/run-pass/cleanup-auto-borrow-obj.rs @@ -29,7 +29,7 @@ impl Trait for Foo {} pub fn main() { { - let _x: &Trait = box Foo as Box; + let _x: &Trait = &*(box Foo as Box); } unsafe { assert!(DROP_RAN); diff --git a/src/test/run-pass/issue-3794.rs b/src/test/run-pass/issue-3794.rs index 9414a6f2302..54225bbe01e 100644 --- a/src/test/run-pass/issue-3794.rs +++ b/src/test/run-pass/issue-3794.rs @@ -36,5 +36,5 @@ pub fn main() { let s: Box = box S { s: 5 }; print_s(&*s); let t: Box = s as Box; - print_t(t); + print_t(&*t); } diff --git a/src/test/run-pass/new-box.rs b/src/test/run-pass/new-box.rs index 38f552e9a98..8531fd5f975 100644 --- a/src/test/run-pass/new-box.rs +++ b/src/test/run-pass/new-box.rs @@ -29,7 +29,7 @@ impl Trait for Struct { fn g(x: Box) { x.printme(); - let y: &Trait = x; + let y: &Trait = &*x; y.printme(); } diff --git a/src/test/run-pass/regions-early-bound-trait-param.rs b/src/test/run-pass/regions-early-bound-trait-param.rs index 27ef90d7376..c732d20a156 100644 --- a/src/test/run-pass/regions-early-bound-trait-param.rs +++ b/src/test/run-pass/regions-early-bound-trait-param.rs @@ -120,8 +120,8 @@ pub fn main() { assert_eq!(field_invoke2(&s2), 3); let m : Box = make_val(); - assert_eq!(object_invoke1(m), (4,5)); - assert_eq!(object_invoke2(m), 5); + assert_eq!(object_invoke1(&*m), (4,5)); + assert_eq!(object_invoke2(&*m), 5); // The RefMakerTrait above is pretty strange (i.e. it is strange // to consume a value of type T and return a &T). Easiest thing