Navigation Menu

Skip to content

Commit

Permalink
librustc: Remove cross-borrowing of Box<T> to &T from the language,
Browse files Browse the repository at this point in the history
except where trait objects are involved.

Part of issue #15349, though I'm leaving it open for trait objects.
Cross borrowing for trait objects remains because it is needed until we
have DST.

This will break code like:

    fn foo(x: &int) { ... }

    let a = box 3i;
    foo(a);

Change this code to:

    fn foo(x: &int) { ... }

    let a = box 3i;
    foo(&*a);

[breaking-change]
  • Loading branch information
pcwalton committed Jul 17, 2014
1 parent ca24abd commit de70d76
Show file tree
Hide file tree
Showing 72 changed files with 206 additions and 204 deletions.
9 changes: 4 additions & 5 deletions src/doc/guide-lifetimes.md
Expand Up @@ -67,7 +67,7 @@ Now we can call `compute_distance()`:
# let on_the_stack : Point = Point{x: 3.0, y: 4.0};
# let on_the_heap : Box<Point> = box Point{x: 7.0, y: 9.0};
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&on_the_stack, on_the_heap);
compute_distance(&on_the_stack, &*on_the_heap);
~~~

Here, the `&` operator takes the address of the variable
Expand All @@ -77,10 +77,9 @@ value. We also call this _borrowing_ the local variable
`on_the_stack`, because we have created an alias: that is, another
name for the same data.

In the case of `on_the_heap`, however, no explicit action is necessary.
The compiler will automatically convert a box point to a reference like &point.
This is another form of borrowing; in this case, the contents of the owned box
are being lent out.
Likewise, in the case of `owned_box`,
the `&` operator is used in conjunction with the `*` operator
to take a reference to the contents of the box.

Whenever a caller lends data to a callee, there are some limitations on what
the caller can do with the original. For example, if the contents of a
Expand Down
2 changes: 1 addition & 1 deletion src/doc/guide-pointers.md
Expand Up @@ -279,7 +279,7 @@ fn main() {
let origin = &Point { x: 0.0, y: 0.0 };
let p1 = box Point { x: 5.0, y: 3.0 };

println!("{}", compute_distance(origin, p1));
println!("{}", compute_distance(origin, &*p1));
}
~~~

Expand Down
2 changes: 1 addition & 1 deletion src/doc/rust.md
Expand Up @@ -3243,7 +3243,7 @@ enum List { Nil, Cons(uint, Box<List>) }
fn is_sorted(list: &List) -> bool {
match *list {
Nil | Cons(_, box Nil) => true,
Cons(x, ref r @ box Cons(y, _)) => (x <= y) && is_sorted(*r)
Cons(x, ref r @ box Cons(y, _)) => (x <= y) && is_sorted(&**r)
}
}
Expand Down
10 changes: 4 additions & 6 deletions src/doc/tutorial.md
Expand Up @@ -1470,7 +1470,7 @@ Now we can call `compute_distance()` in various ways:
# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
# let on_the_heap : Box<Point> = box Point { x: 7.0, y: 9.0 };
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&on_the_stack, on_the_heap);
compute_distance(&on_the_stack, &*on_the_heap);
~~~

Here the `&` operator is used to take the address of the variable
Expand All @@ -1480,11 +1480,9 @@ reference. We also call this _borrowing_ the local variable
`on_the_stack`, because we are creating an alias: that is, another
route to the same data.

In the case of `owned_box`, however, no
explicit action is necessary. The compiler will automatically convert
a box `box point` to a reference like
`&point`. This is another form of borrowing; in this case, the
contents of the owned box are being lent out.
Likewise, in the case of `owned_box`,
the `&` operator is used in conjunction with the `*` operator
to take a reference to the contents of the box.

Whenever a value is borrowed, there are some limitations on what you
can do with the original. For example, if the contents of a variable
Expand Down
6 changes: 4 additions & 2 deletions src/liballoc/boxed.rs
Expand Up @@ -67,7 +67,7 @@ impl<T:PartialEq> PartialEq for Box<T> {
impl<T:PartialOrd> PartialOrd for Box<T> {
#[inline]
fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
(**self).partial_cmp(*other)
(**self).partial_cmp(&**other)
}
#[inline]
fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
Expand All @@ -80,7 +80,9 @@ impl<T:PartialOrd> PartialOrd for Box<T> {
}
impl<T: Ord> Ord for Box<T> {
#[inline]
fn cmp(&self, other: &Box<T>) -> Ordering { (**self).cmp(*other) }
fn cmp(&self, other: &Box<T>) -> Ordering {
(**self).cmp(&**other)
}
}
impl<T: Eq> Eq for Box<T> {}

Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/treemap.rs
Expand Up @@ -516,7 +516,7 @@ define_iterator! {
fn deref<'a, K, V>(node: &'a Option<Box<TreeNode<K, V>>>) -> *const TreeNode<K, V> {
match *node {
Some(ref n) => {
let n: &TreeNode<K, V> = *n;
let n: &TreeNode<K, V> = &**n;
n as *const TreeNode<K, V>
}
None => ptr::null()
Expand Down
4 changes: 2 additions & 2 deletions src/libregex_macros/lib.rs
Expand Up @@ -623,15 +623,15 @@ fn parse(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Option<String> {
_ => {
cx.span_err(entry.span, format!(
"expected string literal but got `{}`",
pprust::lit_to_string(lit)).as_slice());
pprust::lit_to_string(&*lit)).as_slice());
return None
}
}
}
_ => {
cx.span_err(entry.span, format!(
"expected string literal but got `{}`",
pprust::expr_to_string(entry)).as_slice());
pprust::expr_to_string(&*entry)).as_slice());
return None
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/driver/driver.rs
Expand Up @@ -799,7 +799,7 @@ fn print_flowgraph<W:io::Writer>(variants: Vec<borrowck_dot::Variant>,
let ty_cx = &analysis.ty_cx;
let cfg = match code {
blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block),
blocks::FnLikeCode(fn_like) => cfg::CFG::new(ty_cx, fn_like.body()),
blocks::FnLikeCode(fn_like) => cfg::CFG::new(ty_cx, &*fn_like.body()),
};
debug!("cfg: {:?}", cfg);

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/encoder.rs
Expand Up @@ -1248,7 +1248,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_method_sort(ebml_w, 'p');
encode_inlined_item(ecx, ebml_w,
IIMethodRef(def_id, true, &*m));
encode_method_argument_names(ebml_w, m.pe_fn_decl());
encode_method_argument_names(ebml_w, &*m.pe_fn_decl());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/tyencode.rs
Expand Up @@ -267,7 +267,7 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
}
ty::ty_closure(ref f) => {
mywrite!(w, "f");
enc_closure_ty(w, cx, *f);
enc_closure_ty(w, cx, &**f);
}
ty::ty_bare_fn(ref f) => {
mywrite!(w, "F");
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/astencode.rs
Expand Up @@ -1557,7 +1557,7 @@ fn test_simplification() {
return alist {eq_fn: eq_int, data: Vec::new()};
}
).unwrap();
let item_in = e::IIItemRef(item);
let item_in = e::IIItemRef(&*item);
let item_out = simplify_ast(item_in);
let item_exp = ast::IIItem(quote_item!(cx,
fn new_int_alist<B>() -> alist<int, B> {
Expand All @@ -1566,7 +1566,8 @@ fn test_simplification() {
).unwrap());
match (item_out, item_exp) {
(ast::IIItem(item_out), ast::IIItem(item_exp)) => {
assert!(pprust::item_to_string(item_out) == pprust::item_to_string(item_exp));
assert!(pprust::item_to_string(&*item_out) ==
pprust::item_to_string(&*item_exp));
}
_ => fail!()
}
Expand Down
9 changes: 7 additions & 2 deletions src/librustc/middle/borrowck/mod.rs
Expand Up @@ -216,8 +216,13 @@ pub fn build_borrowck_dataflow_data_for_fn<'a>(

let p = input.fn_parts;

let dataflow_data = build_borrowck_dataflow_data(
&mut bccx, &p.kind, p.decl, input.cfg, p.body, p.span, p.id);
let dataflow_data = build_borrowck_dataflow_data(&mut bccx,
&p.kind,
&*p.decl,
input.cfg,
&*p.body,
p.span,
p.id);

(bccx, dataflow_data)
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/check_match.rs
Expand Up @@ -47,7 +47,9 @@ impl fmt::Show for Matrix {

let &Matrix(ref m) = self;
let pretty_printed_matrix: Vec<Vec<String>> = m.iter().map(|row| {
row.iter().map(|&pat| pat_to_string(pat)).collect::<Vec<String>>()
row.iter()
.map(|&pat| pat_to_string(&*pat))
.collect::<Vec<String>>()
}).collect();

let column_count = m.iter().map(|row| row.len()).max().unwrap_or(0u);
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/middle/dead.rs
Expand Up @@ -212,7 +212,7 @@ impl<'a> MarkSymbolVisitor<'a> {
visit::walk_trait_method(self, &*trait_method, ctxt);
}
ast_map::NodeMethod(method) => {
visit::walk_block(self, method.pe_body(), ctxt);
visit::walk_block(self, &*method.pe_body(), ctxt);
}
ast_map::NodeForeignItem(foreign_item) => {
visit::walk_foreign_item(self, &*foreign_item, ctxt);
Expand Down Expand Up @@ -520,7 +520,9 @@ impl<'a> Visitor<()> for DeadVisitor<'a> {
// Overwrite so that we don't warn the trait method itself.
fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
match *trait_method {
ast::Provided(ref method) => visit::walk_block(self, method.pe_body(), ()),
ast::Provided(ref method) => {
visit::walk_block(self, &*method.pe_body(), ())
}
ast::Required(_) => ()
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/reachable.rs
Expand Up @@ -316,14 +316,14 @@ impl<'a> ReachableContext<'a> {
// Keep going, nothing to get exported
}
ast::Provided(ref method) => {
visit::walk_block(self, method.pe_body(), ())
visit::walk_block(self, &*method.pe_body(), ())
}
}
}
ast_map::NodeMethod(method) => {
let did = self.tcx.map.get_parent_did(search_item);
if method_might_be_inlined(self.tcx, &*method, did) {
visit::walk_block(self, method.pe_body(), ())
visit::walk_block(self, &*method.pe_body(), ())
}
}
// Nothing to recurse on for these
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/resolve.rs
Expand Up @@ -3707,7 +3707,7 @@ impl<'a> Resolver<'a> {

match ty_m.explicit_self.node {
SelfExplicit(ref typ, _) => {
this.resolve_type(*typ)
this.resolve_type(&**typ)
}
_ => {}
}
Expand Down Expand Up @@ -4044,7 +4044,7 @@ impl<'a> Resolver<'a> {
rib_kind);

match method.pe_explicit_self().node {
SelfExplicit(ref typ, _) => self.resolve_type(*typ),
SelfExplicit(ref typ, _) => self.resolve_type(&**typ),
_ => {}
}

Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/save/mod.rs
Expand Up @@ -356,9 +356,10 @@ impl <'l> DxrVisitor<'l> {
for arg in method.pe_fn_decl().inputs.iter() {
self.visit_ty(&*arg.ty, e);
}
self.visit_ty(method.pe_fn_decl().output, e);
self.visit_ty(&*method.pe_fn_decl().output, e);
// walk the fn body
self.visit_block(method.pe_body(), DxrVisitorEnv::new_nested(method.id));
self.visit_block(&*method.pe_body(),
DxrVisitorEnv::new_nested(method.id));

self.process_generic_params(method.pe_generics(),
method.span,
Expand Down
8 changes: 5 additions & 3 deletions src/librustc/middle/trans/_match.rs
Expand Up @@ -491,7 +491,7 @@ fn enter_default<'a, 'b>(

// Collect all of the matches that can match against anything.
enter_match(bcx, dm, m, col, val, |pats| {
if pat_is_binding_or_wild(dm, pats[col]) {
if pat_is_binding_or_wild(dm, &*pats[col]) {
Some(Vec::from_slice(pats.slice_to(col)).append(pats.slice_from(col + 1)))
} else {
None
Expand Down Expand Up @@ -546,8 +546,10 @@ fn enter_opt<'a, 'b>(
let _indenter = indenter();

let ctor = match opt {
&lit(x) => check_match::ConstantValue(const_eval::eval_const_expr(
bcx.tcx(), lit_to_expr(bcx.tcx(), &x))),
&lit(x) => {
check_match::ConstantValue(const_eval::eval_const_expr(
bcx.tcx(), &*lit_to_expr(bcx.tcx(), &x)))
}
&range(ref lo, ref hi) => check_match::ConstantRange(
const_eval::eval_const_expr(bcx.tcx(), &**lo),
const_eval::eval_const_expr(bcx.tcx(), &**hi)
Expand Down
9 changes: 7 additions & 2 deletions src/librustc/middle/trans/meth.rs
Expand Up @@ -68,8 +68,13 @@ pub fn trans_impl(ccx: &CrateContext,
for method in methods.iter() {
if method.pe_generics().ty_params.len() == 0u {
let llfn = get_item_val(ccx, method.id);
trans_fn(ccx, method.pe_fn_decl(), method.pe_body(),
llfn, &param_substs::empty(), method.id, []);
trans_fn(ccx,
&*method.pe_fn_decl(),
&*method.pe_body(),
llfn,
&param_substs::empty(),
method.id,
[]);
} else {
let mut v = TransItemVisitor{ ccx: ccx };
visit::walk_method_helper(&mut v, &**method, ());
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/ty.rs
Expand Up @@ -2038,7 +2038,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
}

ty_closure(ref c) => {
closure_contents(cx, *c)
closure_contents(cx, &**c)
}

ty_box(typ) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/astconv.rs
Expand Up @@ -1018,7 +1018,7 @@ fn determine_explicit_self_category<AC:AstConv,
}
ast::SelfUniq(_) => ty::ByBoxExplicitSelfCategory,
ast::SelfExplicit(ast_type, _) => {
let explicit_type = ast_ty_to_ty(this, rscope, ast_type);
let explicit_type = ast_ty_to_ty(this, rscope, &*ast_type);

{
let inference_context = infer::new_infer_ctxt(this.tcx());
Expand Down
26 changes: 17 additions & 9 deletions src/librustc/middle/typeck/check/mod.rs
Expand Up @@ -764,7 +764,12 @@ fn check_method_body(ccx: &CrateCtxt,

let fty = ty::node_id_to_type(ccx.tcx, method.id);

check_bare_fn(ccx, method.pe_fn_decl(), method.pe_body(), method.id, fty, param_env);
check_bare_fn(ccx,
&*method.pe_fn_decl(),
&*method.pe_body(),
method.id,
fty,
param_env);
}

fn check_impl_methods_against_trait(ccx: &CrateCtxt,
Expand Down Expand Up @@ -2370,7 +2375,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,

if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
// Shift is a special case: rhs must be uint, no matter what lhs is
check_expr_has_type(fcx, rhs, ty::mk_uint());
check_expr_has_type(fcx, &*rhs, ty::mk_uint());
fcx.write_ty(expr.id, lhs_t);
return;
}
Expand Down Expand Up @@ -2957,7 +2962,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
}

ast::ExprLit(lit) => {
let typ = check_lit(fcx, lit, expected);
let typ = check_lit(fcx, &*lit, expected);
fcx.write_ty(id, typ);
}
ast::ExprBinary(op, ref lhs, ref rhs) => {
Expand Down Expand Up @@ -3164,8 +3169,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
fcx.write_bot(id);
}
ast::ExprParen(a) => {
check_expr_with_expectation_and_lvalue_pref(fcx, a, expected, lvalue_pref);
fcx.write_ty(id, fcx.expr_ty(a));
check_expr_with_expectation_and_lvalue_pref(fcx,
&*a,
expected,
lvalue_pref);
fcx.write_ty(id, fcx.expr_ty(&*a));
}
ast::ExprAssign(ref lhs, ref rhs) => {
check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
Expand Down Expand Up @@ -3326,8 +3334,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)),
_ => NoExpectation
};
check_expr_with_expectation(fcx, *e, opt_hint);
let t = fcx.expr_ty(*e);
check_expr_with_expectation(fcx, &**e, opt_hint);
let t = fcx.expr_ty(&**e);
err_field = err_field || ty::type_is_error(t);
bot_field = bot_field || ty::type_is_bot(t);
t
Expand Down Expand Up @@ -3674,8 +3682,8 @@ fn check_block_with_expected(fcx: &FnCtxt,
e.span,
"unreachable expression".to_string());
}
check_expr_with_expectation(fcx, e, expected);
let ety = fcx.expr_ty(e);
check_expr_with_expectation(fcx, &*e, expected);
let ety = fcx.expr_ty(&*e);
fcx.write_ty(blk.id, ety);
if any_err {
fcx.write_error(blk.id);
Expand Down

5 comments on commit de70d76

@bors
Copy link
Contributor

@bors bors commented on de70d76 Jul 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at pcwalton@de70d76

@bors
Copy link
Contributor

@bors bors commented on de70d76 Jul 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging pcwalton/rust/cross-borrowing = de70d76 into auto

@bors
Copy link
Contributor

@bors bors commented on de70d76 Jul 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pcwalton/rust/cross-borrowing = de70d76 merged ok, testing candidate = e288fc6

@bors
Copy link
Contributor

@bors bors commented on de70d76 Jul 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = e288fc6

Please sign in to comment.