Skip to content

Commit e86d414

Browse files
committed
auto merge of #8497 : nikomatsakis/rust/improvements-to-object-coercion, r=pcwalton
While looking over the code for object coercion, I realized that it wasn't quite handling freezing and reborrowing correctly. Tweak the code, adding tests for the relevant cases. r? @pcwalton
2 parents 7585b34 + bf2d3c8 commit e86d414

File tree

5 files changed

+126
-13
lines changed

5 files changed

+126
-13
lines changed

src/librustc/middle/typeck/check/regionck.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ fn visit_expr(expr: @ast::expr, (rcx, v): (@mut Rcx, rvt)) {
391391
let target_ty = rcx.resolve_node_type(expr.id);
392392
match ty::get(target_ty).sty {
393393
ty::ty_trait(_, _, ty::RegionTraitStore(trait_region), _, _) => {
394-
let source_ty = rcx.fcx.expr_ty(source);
394+
let source_ty = rcx.resolve_expr_type_adjusted(source);
395395
constrain_regions_in_type(
396396
rcx,
397397
trait_region,
@@ -1153,17 +1153,20 @@ pub mod guarantor {
11531153
match ty::get(ty).sty {
11541154
ty::ty_rptr(r, _) |
11551155
ty::ty_evec(_, ty::vstore_slice(r)) |
1156+
ty::ty_trait(_, _, ty::RegionTraitStore(r), _, _) |
11561157
ty::ty_estr(ty::vstore_slice(r)) => {
11571158
BorrowedPointer(r)
11581159
}
11591160
ty::ty_uniq(*) |
11601161
ty::ty_estr(ty::vstore_uniq) |
1162+
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
11611163
ty::ty_evec(_, ty::vstore_uniq) => {
11621164
OwnedPointer
11631165
}
11641166
ty::ty_box(*) |
11651167
ty::ty_ptr(*) |
11661168
ty::ty_evec(_, ty::vstore_box) |
1169+
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) |
11671170
ty::ty_estr(ty::vstore_box) => {
11681171
OtherPointer
11691172
}

src/librustc/middle/typeck/infer/coercion.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ impl Coerce {
121121
};
122122
}
123123

124-
ty::ty_trait(_, _, ty::RegionTraitStore(*), _, _) => {
124+
ty::ty_trait(_, _, ty::RegionTraitStore(*), m, _) => {
125125
return do self.unpack_actual_value(a) |sty_a| {
126-
self.coerce_borrowed_object(a, sty_a, b)
126+
self.coerce_borrowed_object(a, sty_a, b, m)
127127
};
128128
}
129129

@@ -274,34 +274,30 @@ impl Coerce {
274274
fn coerce_borrowed_object(&self,
275275
a: ty::t,
276276
sty_a: &ty::sty,
277-
b: ty::t) -> CoerceResult
277+
b: ty::t,
278+
b_mutbl: ast::mutability) -> CoerceResult
278279
{
279280
debug!("coerce_borrowed_object(a=%s, sty_a=%?, b=%s)",
280281
a.inf_str(self.infcx), sty_a,
281282
b.inf_str(self.infcx));
282283

283284
let tcx = self.infcx.tcx;
284285
let r_a = self.infcx.next_region_var(Coercion(self.trace));
285-
let trt_mut;
286286

287287
let a_borrowed = match *sty_a {
288-
ty::ty_trait(_, _, ty::RegionTraitStore(_), _, _) => {
289-
return self.subtype(a, b);
290-
}
291-
ty::ty_trait(did, ref substs, _, m, b) => {
292-
trt_mut = m;
288+
ty::ty_trait(did, ref substs, _, _, b) => {
293289
ty::mk_trait(tcx, did, substs.clone(),
294-
ty::RegionTraitStore(r_a), m, b)
290+
ty::RegionTraitStore(r_a), b_mutbl, b)
295291
}
296292
_ => {
297293
return self.subtype(a, b);
298294
}
299295
};
300296

301-
if_ok!(self.tys(a_borrowed, b));
297+
if_ok!(self.subtype(a_borrowed, b));
302298
Ok(Some(@AutoDerefRef(AutoDerefRef {
303299
autoderefs: 0,
304-
autoref: Some(AutoBorrowObj(r_a, trt_mut))
300+
autoref: Some(AutoBorrowObj(r_a, b_mutbl))
305301
})))
306302
}
307303

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// error-pattern:borrowed
2+
3+
trait Foo {
4+
fn foo(&self, @mut int);
5+
}
6+
7+
impl Foo for int {
8+
fn foo(&self, x: @mut int) {
9+
*x += *self;
10+
}
11+
}
12+
13+
fn it_takes_two(f: &Foo, g: &mut Foo) {
14+
}
15+
16+
fn main() {
17+
let x = @mut 3_i;
18+
let y = x as @mut Foo;
19+
let z = y;
20+
21+
it_takes_two(y, z);
22+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we can coerce an `@Object` to an `&Object`
12+
13+
trait Foo {
14+
fn foo(&self) -> uint;
15+
fn bar(&mut self) -> uint;
16+
}
17+
18+
impl Foo for uint {
19+
fn foo(&self) -> uint {
20+
*self
21+
}
22+
23+
fn bar(&mut self) -> uint {
24+
*self += 1;
25+
*self
26+
}
27+
}
28+
29+
fn do_it_mut(obj: &mut Foo) {
30+
let x = obj.bar();
31+
let y = obj.foo();
32+
assert_eq!(x, y);
33+
34+
do_it_imm(obj, y);
35+
}
36+
37+
fn do_it_imm(obj: &Foo, v: uint) {
38+
let y = obj.foo();
39+
assert_eq!(v, y);
40+
}
41+
42+
fn main() {
43+
let mut x = 22_u;
44+
let obj = &mut x as &mut Foo;
45+
do_it_mut(obj);
46+
do_it_imm(obj, 23u);
47+
do_it_mut(obj);
48+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we can coerce an `@Object` to an `&Object`
12+
13+
trait Foo {
14+
fn foo(&self) -> uint;
15+
fn bar(&mut self) -> uint;
16+
}
17+
18+
impl Foo for uint {
19+
fn foo(&self) -> uint {
20+
*self
21+
}
22+
23+
fn bar(&mut self) -> uint {
24+
*self += 1;
25+
*self
26+
}
27+
}
28+
29+
fn do_it_mut(obj: &mut Foo) {
30+
let x = obj.bar();
31+
let y = obj.foo();
32+
assert_eq!(x, y);
33+
}
34+
35+
fn do_it_imm(obj: &Foo, v: uint) {
36+
let y = obj.foo();
37+
assert_eq!(v, y);
38+
}
39+
40+
fn main() {
41+
let x = @mut 22u as @mut Foo;
42+
do_it_mut(x);
43+
do_it_imm(x, 23u);
44+
}

0 commit comments

Comments
 (0)