Region + borrow checker support and tests for overloaded autoderef.
This commit is contained in:
parent
feedd37653
commit
27c62449db
8 changed files with 540 additions and 24 deletions
|
|
@ -0,0 +1,131 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test how overloaded deref interacts with borrows when DerefMut
|
||||
// is implemented.
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
struct Own<T> {
|
||||
value: *mut T
|
||||
}
|
||||
|
||||
impl<T> Deref<T> for Own<T> {
|
||||
fn deref<'a>(&'a self) -> &'a T {
|
||||
unsafe { &*self.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut<T> for Own<T> {
|
||||
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
|
||||
unsafe { &mut *self.value }
|
||||
}
|
||||
}
|
||||
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn get(&self) -> (int, int) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn set(&mut self, x: int, y: int) {
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
fn x_ref<'a>(&'a self) -> &'a int {
|
||||
&self.x
|
||||
}
|
||||
|
||||
fn y_mut<'a>(&'a mut self) -> &'a mut int {
|
||||
&mut self.y
|
||||
}
|
||||
}
|
||||
|
||||
fn deref_imm_field(x: Own<Point>) {
|
||||
let _i = &x.y;
|
||||
}
|
||||
|
||||
fn deref_mut_field1(x: Own<Point>) {
|
||||
let _i = &mut x.y; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_mut_field2(mut x: Own<Point>) {
|
||||
let _i = &mut x.y;
|
||||
}
|
||||
|
||||
fn deref_extend_field<'a>(x: &'a Own<Point>) -> &'a int {
|
||||
&x.y
|
||||
}
|
||||
|
||||
fn deref_extend_mut_field1<'a>(x: &'a Own<Point>) -> &'a mut int {
|
||||
&mut x.y //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_extend_mut_field2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
|
||||
&mut x.y
|
||||
}
|
||||
|
||||
fn assign_field1<'a>(x: Own<Point>) {
|
||||
x.y = 3; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn assign_field2<'a>(x: &'a Own<Point>) {
|
||||
x.y = 3; //~ ERROR cannot assign
|
||||
}
|
||||
|
||||
fn assign_field3<'a>(x: &'a mut Own<Point>) {
|
||||
x.y = 3;
|
||||
}
|
||||
|
||||
// FIXME(eddyb) #12825 This shouldn't attempt to call deref_mut.
|
||||
/*
|
||||
fn deref_imm_method(x: Own<Point>) {
|
||||
let _i = x.get();
|
||||
}
|
||||
*/
|
||||
|
||||
fn deref_mut_method1(x: Own<Point>) {
|
||||
x.set(0, 0); //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_mut_method2(mut x: Own<Point>) {
|
||||
x.set(0, 0);
|
||||
}
|
||||
|
||||
fn deref_extend_method<'a>(x: &'a Own<Point>) -> &'a int {
|
||||
x.x_ref()
|
||||
}
|
||||
|
||||
fn deref_extend_mut_method1<'a>(x: &'a Own<Point>) -> &'a mut int {
|
||||
x.y_mut() //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_extend_mut_method2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
|
||||
x.y_mut()
|
||||
}
|
||||
|
||||
fn assign_method1<'a>(x: Own<Point>) {
|
||||
*x.y_mut() = 3; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn assign_method2<'a>(x: &'a Own<Point>) {
|
||||
*x.y_mut() = 3; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn assign_method3<'a>(x: &'a mut Own<Point>) {
|
||||
*x.y_mut() = 3;
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
122
src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs
Normal file
122
src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test how overloaded deref interacts with borrows when only
|
||||
// Deref and not DerefMut is implemented.
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
struct Rc<T> {
|
||||
value: *T
|
||||
}
|
||||
|
||||
impl<T> Deref<T> for Rc<T> {
|
||||
fn deref<'a>(&'a self) -> &'a T {
|
||||
unsafe { &*self.value }
|
||||
}
|
||||
}
|
||||
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn get(&self) -> (int, int) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn set(&mut self, x: int, y: int) {
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
fn x_ref<'a>(&'a self) -> &'a int {
|
||||
&self.x
|
||||
}
|
||||
|
||||
fn y_mut<'a>(&'a mut self) -> &'a mut int {
|
||||
&mut self.y
|
||||
}
|
||||
}
|
||||
|
||||
fn deref_imm_field(x: Rc<Point>) {
|
||||
let _i = &x.y;
|
||||
}
|
||||
|
||||
fn deref_mut_field1(x: Rc<Point>) {
|
||||
let _i = &mut x.y; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_mut_field2(mut x: Rc<Point>) {
|
||||
let _i = &mut x.y; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_extend_field<'a>(x: &'a Rc<Point>) -> &'a int {
|
||||
&x.y
|
||||
}
|
||||
|
||||
fn deref_extend_mut_field1<'a>(x: &'a Rc<Point>) -> &'a mut int {
|
||||
&mut x.y //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_extend_mut_field2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
|
||||
&mut x.y //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn assign_field1<'a>(x: Rc<Point>) {
|
||||
x.y = 3; //~ ERROR cannot assign
|
||||
}
|
||||
|
||||
fn assign_field2<'a>(x: &'a Rc<Point>) {
|
||||
x.y = 3; //~ ERROR cannot assign
|
||||
}
|
||||
|
||||
fn assign_field3<'a>(x: &'a mut Rc<Point>) {
|
||||
x.y = 3; //~ ERROR cannot assign
|
||||
}
|
||||
|
||||
fn deref_imm_method(x: Rc<Point>) {
|
||||
let _i = x.get();
|
||||
}
|
||||
|
||||
fn deref_mut_method1(x: Rc<Point>) {
|
||||
x.set(0, 0); //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_mut_method2(mut x: Rc<Point>) {
|
||||
x.set(0, 0); //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_extend_method<'a>(x: &'a Rc<Point>) -> &'a int {
|
||||
x.x_ref()
|
||||
}
|
||||
|
||||
fn deref_extend_mut_method1<'a>(x: &'a Rc<Point>) -> &'a mut int {
|
||||
x.y_mut() //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn deref_extend_mut_method2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
|
||||
x.y_mut() //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn assign_method1<'a>(x: Rc<Point>) {
|
||||
*x.y_mut() = 3; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn assign_method2<'a>(x: &'a Rc<Point>) {
|
||||
*x.y_mut() = 3; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
fn assign_method3<'a>(x: &'a mut Rc<Point>) {
|
||||
*x.y_mut() = 3; //~ ERROR cannot borrow
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn main() {
|
||||
let _x = Rc::new(vec!(1, 2)).move_iter();
|
||||
//~^ ERROR cannot move out of dereference of `&`-pointer
|
||||
}
|
||||
82
src/test/run-pass/overloaded-autoderef-count.rs
Normal file
82
src/test/run-pass/overloaded-autoderef-count.rs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::vec_ng::Vec;
|
||||
|
||||
#[deriving(Eq)]
|
||||
struct DerefCounter<T> {
|
||||
count_imm: Cell<uint>,
|
||||
count_mut: uint,
|
||||
value: T
|
||||
}
|
||||
|
||||
impl<T> DerefCounter<T> {
|
||||
fn new(value: T) -> DerefCounter<T> {
|
||||
DerefCounter {
|
||||
count_imm: Cell::new(0),
|
||||
count_mut: 0,
|
||||
value: value
|
||||
}
|
||||
}
|
||||
|
||||
fn counts(&self) -> (uint, uint) {
|
||||
(self.count_imm.get(), self.count_mut)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref<T> for DerefCounter<T> {
|
||||
fn deref<'a>(&'a self) -> &'a T {
|
||||
self.count_imm.set(self.count_imm.get() + 1);
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut<T> for DerefCounter<T> {
|
||||
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
|
||||
self.count_mut += 1;
|
||||
&mut self.value
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Eq, Show)]
|
||||
struct Point {
|
||||
x: int,
|
||||
y: int
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn get(&self) -> (int, int) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut p = DerefCounter::new(Point {x: 0, y: 0});
|
||||
|
||||
let _ = p.x;
|
||||
assert_eq!(p.counts(), (1, 0));
|
||||
|
||||
let _ = &p.x;
|
||||
assert_eq!(p.counts(), (2, 0));
|
||||
|
||||
let _ = &mut p.y;
|
||||
assert_eq!(p.counts(), (2, 1));
|
||||
|
||||
p.x += 3;
|
||||
assert_eq!(p.counts(), (2, 2));
|
||||
|
||||
p.get();
|
||||
assert_eq!(p.counts(), (2, 3));
|
||||
|
||||
// Check the final state.
|
||||
assert_eq!(*p, Point {x: 3, y: 0});
|
||||
}
|
||||
24
src/test/run-pass/overloaded-autoderef-indexing.rs
Normal file
24
src/test/run-pass/overloaded-autoderef-indexing.rs
Normal file
|
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct DerefArray<'a, T> {
|
||||
inner: &'a [T]
|
||||
}
|
||||
|
||||
impl<'a, T> Deref<&'a [T]> for DerefArray<'a, T> {
|
||||
fn deref<'b>(&'b self) -> &'b &'a [T] {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let a = &[1, 2, 3];
|
||||
assert_eq!(DerefArray {inner: a}[1], 2);
|
||||
}
|
||||
71
src/test/run-pass/overloaded-autoderef-order.rs
Normal file
71
src/test/run-pass/overloaded-autoderef-order.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
struct DerefWrapper<X, Y> {
|
||||
x: X,
|
||||
y: Y
|
||||
}
|
||||
|
||||
impl<X, Y> DerefWrapper<X, Y> {
|
||||
fn get_x(self) -> X {
|
||||
self.x
|
||||
}
|
||||
}
|
||||
|
||||
impl<X, Y> Deref<Y> for DerefWrapper<X, Y> {
|
||||
fn deref<'a>(&'a self) -> &'a Y {
|
||||
&self.y
|
||||
}
|
||||
}
|
||||
|
||||
mod priv_test {
|
||||
pub struct DerefWrapperHideX<X, Y> {
|
||||
priv x: X,
|
||||
y: Y
|
||||
}
|
||||
|
||||
impl<X, Y> DerefWrapperHideX<X, Y> {
|
||||
pub fn new(x: X, y: Y) -> DerefWrapperHideX<X, Y> {
|
||||
DerefWrapperHideX {
|
||||
x: x,
|
||||
y: y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<X, Y> Deref<Y> for DerefWrapperHideX<X, Y> {
|
||||
fn deref<'a>(&'a self) -> &'a Y {
|
||||
&self.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let nested = DerefWrapper {x: true, y: DerefWrapper {x: 0, y: 1}};
|
||||
|
||||
// Use the first field that you can find.
|
||||
assert_eq!(nested.x, true);
|
||||
assert_eq!((*nested).x, 0);
|
||||
|
||||
// Same for methods, even though there are multiple
|
||||
// candidates (at different nesting levels).
|
||||
assert_eq!(nested.get_x(), true);
|
||||
assert_eq!((*nested).get_x(), 0);
|
||||
|
||||
// Also go through multiple levels of indirection.
|
||||
assert_eq!(Rc::new(nested).x, true);
|
||||
|
||||
let nested_priv = priv_test::DerefWrapperHideX::new(true, DerefWrapper {x: 0, y: 1});
|
||||
// FIXME(eddyb) #12808 should skip private fields.
|
||||
// assert_eq!(nested_priv.x, 0);
|
||||
assert_eq!((*nested_priv).x, 0);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue